Results 1 to 9 of 9

Thread: WithEvents of Excel.Application Events

  1. #1
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,455
    Rep Power
    10

    WithEvents of Excel.Application Events

    (This is post 2294)
    There is a summary / revision in post #6 https://excelfox.com/forum/showthrea...ll=1#post15200 This will most likely only be useful as a revision later, but might also help some who have perhaps already tackled this subject and need quickly to revise the Format of a typical solution



    WithEvents of Excel.Application

    Post #1 Introduction and Revision: How we get macros to run automatically…
    In Excel things get done. We tend to use the jargon: " "Events" occur ". Usually to do this some internal and/or high level coding is in action to do this. In VBA coding we have the option to "hang on" procedures to this coding so that we can arrange that other things are done with or at some point within these "Events" . The end effect is that we can "automate" things, that is to say some of our coding / procedures can be started automatically when something else happens/ when an event occurs.

    Post #1: Review of some relevant basic programming concepts
    It is difficult to explain this subject without reviewing some other somewhat imprecisely defined concepts…
    This Tutorial Thread, WithEvents of Excel.Application , assumes you have some initial experience and knowledge of event type code things. In other words you are familiar with things like coding procedures which start automatically when you change things in a worksheet. So you may have done some simple code like this - ...._
    Code:
    Private Sub Worksheet_Change(ByVal Target As Range)
     If Target.Address = "$A$1" Then MsgBox prompt:="You just changed the value in the first cell in worksheet " & Me.Name & " in the Workbook " & Me.Parent.Name
    End Sub
    _....
    Last edited by DocAElstein; 01-07-2021 at 02:31 PM.

  2. #2
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,455
    Rep Power
    10

    WithEvents of Excel.Application. Encapsturbation Encapsulation

    WithEvents of Excel.Application. Encapsturbation


    Post #2: Excel Events. Hanging codes on to them
    As discussed in the referenced summary, http://www.excelfox.com/forum/showth...ge10#post10838 , the vaguearities of the Objects concept in Object Orientated Programming , OOP , leads to the idea of certain code modules being referred to simultaneously as both belonging to an object , and being the object itself…
    This has and continues to cause computer engineers to confuse themselves, and in an attempt to make sense of order in a messed up system, they often organise their use of code modules in some way that gives at the appearance of some sense and order or theory..
    Generally it is considered that things happen in Excel, that is to say Excel “works”, as a result of Events occurring to objects. Different objects will have different events associated with them
    Those points are important to accept and bear in mind to avoid confusion in the following notes.

    Organising and finding the Event routines, Encapsturbation
    If we were very clever and had access to all possible Microsoft software then we could probably use some VBA or similar OOP coding to make ourselves the “Excel in front of us”. Some of that has been done for us to get us started.
    As a side note, based on the introduction above, we note that Event routines will generally either be in, or chosen to be in, or only allowed to be put in “object modules”. Programmers will often talk about “Encapsulation” or keeping things “where they belong” without being specific but attempting to sound specific and organised in a disorganised situation. It can be considered as a form of Encapsturbation

    Worksheet Events. The Workbook Events
    These are the events codes most often encountered and often they are the only ones explained under the Theme of events codes. But in fact they are just a small selection of event codes whereby they have been partially already put in place in a way that only loosely ties up with some general order.
    A example, consider a Worksheet object. This thing is simultaneously regarded as the spreadsheet of that worksheet or the worksheet code module. We do not have to make this: This has been pseudo done for us, and is somehow part of the Excel software which we purchased. When we run excel something pseudo of this form has been done , or is done, as the software starts up
    _ A class object of a Worksheet has been made. Possibly one is made for each of the default worksheets that appear. (The number may vary depending on your version of Excel ) So there exist somewhere a very complicated class object and/or class object module , or modules, which we can’t see with the name Worksheet.
    _ A few worksheet objects are made from that class, and for the case of a worksheet, they are “subscribed” to the Events associated with a worksheet. Internally some variables, say for the case of the first worksheet, Sheet1 , will be used pseudo like
    Dim WithEvents Sheet1 As Worksheet
    _ Set Sheet1= New Worksheet

    Briefly, those two lines do the following:
    the Dim gives some initial indication of the type of thing that Sheet1 refers to. This might mean referring to the text/ Blueprint info of the variable type of setting aside a copy of such. In any case it does not apparently require too much computer memory. The variable state, for the case of an object, is typically regarded as Nothing , at this point.
    It is usually considered that a more substantial computer memory is used as a result of Set and New pair. This goes by the name of “instantiation” or similar and is regarded as “making” or “building” the object.
    The exact coding and resulting structure of objects is not clear, that is to say not given openly, and it is not permitted to do those steps in coding for the case of a Worksheet!!!. We are not allowed to instantiate a Worksheet. It is possible that the coding results in some pseudo structure of like
    _________________Workbook.xl__
    ____________ Worksheets Collection Worksheet Class
    ____ Class Sheet1 ___ Class Sheet2 _____ Class Sheet3
    _________ Sheet1 ___ _ _____Sheet2______ _____ Sheet3

    It is not clear or disclosed as which of the lower two levels we actually “see” in the code window or the spreadsheet. We see something of, and have some access to , the Sheet1, Sheet2, Sheet3 type “things”. Sometimes the lower two levels might be considered as the same. Sometimes the code module might be considered as the Class Sheet1 and the spreadsheet as Sheet1.
    So it is all a bit Unclear and open to interpretations.
    Consider some points:_
    _ General coding is permitted in the worksheet code modules in addition to the Event codes. General coding is not permitted in the Class module object which we can create.
    _ We cannot subscribe a variable to the events of a Worksheet, or rather we are permitted to do it from the syntax, but the resulting codes simply do not work!!!…. ( see macro below )
    _ We do not need to do the following to step through a code placed in such a module via F8:
    Tools Options.JPG : http://i.imgur.com/KZUyPnB.jpg
    Break in class modules.JPG : http://i.imgur.com/75Eg6UE.jpg

    So those three facts might suggest that we are at the lower level … better described as an object than a class module

    The story is similar with the object for a workbook. We have a single code module which probably fits into a structure of
    ______________________Excel Application
    ______________________Workbook Class
    _______________________Workbook.xl__

    Once again we cannot instantiate a Workbook. We can write normal codes in the code module that we “see” , etc.. etc… So similar arguments to the worksheet case suggest what we see is a ( single in this case ) object module

    Encapsturbation Attributing Encapsulation
    Encapsturbation is a combination of general and self inflicted actions attempting to give a seeming order to the situation. Attributing factors , rules and general practice are as follows.
    Firstly and not always immediately for any obvious reasoning, ( other than Encapsturbation ) , a couple of things related to where things go and how to get at the codes
    _ Where to put WithEvents
    .(i) WithEvents can only go as procedure level variable. ( So outside of a routine, and placed towards the top of a code module). This will make some sense after writing practical routines: The object must “exist” in order to “catch” events, so a variable inside a routine will be of limited use as the variable will “go out of scope”, that is to say no longer “exist” after the routine ends.
    .(ii) WithEvents can only go in an object or class object code module.
    _( Drop down list, help , pseudo intellisense
    For no obvious particular logical or scientific reason there are a couple of drop down list in code modules. (We mentioned in the previous post that for our common case of the worksheet, it seemed to somehow conveniently fit in ). For object modules you typically can select in the left list between two main heading types.
    One type is meaning general routines and there is just one of those.
    The other type refers to the routines for all the WithEvents objects variables .
    Selecting the general will result in a list in the right drop down of all normal procedures in the code module.
    Selecting the object listed which is subscribed to events will result in a long list in the right drop down of all available routines. This probably does make some sense: Once subscribed the routines are “hooked in” and there. We can choose to add code lines in if we wish. One does come in automatically when you select the object: You need to have the cursor within a code in order to get the relevant list available in the right drop down list: One comes in when you click on the object in the left drop down box. The others come in when you click on them. I would personally have put them all in to avoid confusion, but maybe someone thought it would just look tidier to leave them out until they were actually added to …
    In the following code and screenshots I am in a worksheets object code model and have subscribed an object variable, WsTyp2 , to the event codes of worksheet. This appears to be accepted syntaxly and a second duplicated set of codes are included in the right drop down list. ( The Event routine , Private Sub WsTyp2_SelectionChange(ByVal Target As Range) , using WsTyp2 appears however to be complete without function. This is probably as we are not permitted to Set it to a New instance ). Even when assigning to the existing instance, with , Set WsTyp2 = Me , we still find that the Events code using the subscribed object, WsTyp2 , does not respond to any event . Furthermore neither event code works in a module other than a worksheets code module, which suggests that some form of class object is present which we have no access to determines how the existing events cods work )
    Worksheet Events.JPG: http://i.imgur.com/vq9gQ9u.jpg , WsTyp2 Events.JPG : http://i.imgur.com/GWSNDS9.jpg

    Code:
    Dim WithEvents WsTyp2 As Worksheet
    Sub MakeAWorksheetNot()
     On Error GoTo Bed:
     Set WsTyp2 = New Worksheet ' Errors
     Set WsTyp2 = Me
    Exit Sub: ' Code end without error
    Bed:
     MsgBox prompt:=Err.Number & vbCrLf & Err.Description: Debug.Print Err.Number & vbCrLf & Err.Description ' Ctrl+g from the VB Editor to get copyable message in the Immediate window
    End Sub
    Private Sub WsTyp2_SelectionChange(ByVal Target As Range)
     MsgBox prompt:="You will never see this"
    End Sub
    Private Sub Worksheet_SelectionChange(ByVal Target As Range)
     MsgBox prompt:="You will see this if you select a cell in worksheet with name" & vbCrLf & Me.Name
     Resume Next
    End Sub
    _.____

    Application Events
    This is probably the better start point as these codings have not been tampered , manipulated , prepared in the somewhat hap hazard way that the those already discussed have. As such it is a bit clearer how to go about using them. They can be thought more generally, or more fundamentally, as Event coding and Excel Workbooks
    Last edited by DocAElstein; 01-02-2021 at 10:24 PM.
    ….If you are my competitor, I will try all I can to beat you. But if I do, I will not belittle you. I will Salute you, because without you, I am nothing.
    If you are my enemy, we will try to kick the fucking shit out of you…..
    Winston Churchill, 1939
    Save your Forum..._
    _...KILL A MODERATOR!!

  3. #3
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,455
    Rep Power
    10

    Event coding in Excel spreadsheets(Application Events) Misc

    Post 3: Event coding in Excel spreadsheets. Application Events
    The simple ( non class ) way to do it


    Coding like that discussed in this post are often referred to loosely as “Application Events”. In this thread I have been trying to show that they are a more general and fundamental usage of the event coding to which the more typically known worksheet event type codes belong. The more typically known event codes may sometimes be referred to loosely as “normal event codes” or “standard available event codes

    The general rules and Encapsturbation ideas etc. as discussed so far apply to “Application Events”.
    _(i) WithEvents can only go as procedure level variable. ( So outside of a routine, and placed towards the top of a code module).
    _(ii) WithEvents can only go in an object or class object code module.
    _(i) and _(ii) must be adhered to or a syntax error will arise. (i) makes some sense: In a routine it would not be much use as a variable for an object subscribing to, and therefore “watching for” , events as it would cease to exist at the end of a the routine.
    _(iii) In addition, and further in line with Encapsturbation , it is general practice to insert and use a class module for all or most of the coding relating to a specific use of Application Events. This is a general practice, but is not required.

    As a simple example, consider a simple equivalent to the very first example shown at the start of this thread. We had the following routine in a worksheets code module. ( We were using one of the already available “standard” worksheet event codes). Once again, just for convenience, we make use of Me , so the coding is intended to be used in a code module of a worksheet: Changes in that worksheet are effectively monitored with the event code.
    Here again is that “standard event” routine:
    Right mouse click Or double click in VBA explorer Project window to get code module.JPG : http://i.imgur.com/gsz6s2N.jpg
    Code:
    Private Sub Worksheet_Change(ByVal Target As Range)
        If Target.Address = "$A$1" Then MsgBox prompt:="You just changed the value in the first cell in worksheet " & Me.Name & " in the Workbook " & Me.Parent.Name
    End Sub
    Here is some equivalent coding using “Application Events
    The first routine , Sub InstantiateWsMe() , needs to be run once to “make” the object, WsMe.
    The second routine , Sub WsMe_SheetChange(ByVal Sh As Object, ByVal Target As Range) , will then run automatically when a cell in the worksheet with name given by Me.Name has its value changed.
    Custom Listener_Sheet Change.JPG : http://i.imgur.com/kyE0qKh.jpg
    Code:
    Dim WithEvents  WsMe As Excel.Application ' This must go outside any routines, towards the top of a code module. The code module must be an object module or a class object module. These are rules ( for no particular reason that I can think of). If you do mot adhere to them you will get a syntax error. The first is possibly reasonable: In a routine it would not be much use as a variable for an object subscribing to events as it would cease to exist at the end of a  the routine.
    Sub InstantiateWsMe() '  You must run this once to get the following code to work. If you add or delete any codes in this code module, then you must re run this routine
     Set WsMe = Excel.Application ' Important not to use New here, as we want to subscribe to the current instance of Excel in front of us.
    End Sub
    Sub WsMe_SheetChange(ByVal Sh As Object, ByVal Target As Range)
        If Sh.Name = Me.Name Then ' Then we are in this worksheet. Chenge Me.Name with the worksheet tab name like   "Sheet1" or "MySheet"  etc. for code to monitor a a particular worksheet
           If Target.Address = "$A$1" Then MsgBox prompt:="You just changed the value in the first cell in worksheet " & Me.Name & " in the Workbook " & Me.Parent.Name
        Else '
        End If
    End Sub
    
    Sub TestieCalls() ' This can be used to test the event code
     Call WsMe_SheetChange(Me, Me.Range("A1"))
    End Sub
    Coding of the above form is often referred to loosely as a “listener” or more often “custom listener” when using “Application Events
    ( The above coding needs to go in a Worksheets code module, but only because I am using the Me for convenience to get at a worksheet. Generally such codes can go in any object code module, ( or Class object code modules ) )
    _.____

    Some, not all, event codes have things passed to them in the brackets (___), ( using coding we can’t see ) when they are started. The one used here is passed the Sheet object in which the cell or cells are changed, as well as the Range object of the cells or cells which are changed.

    ( The last code , Sub TestieCalls() , allows us to test the event code )

    _.___

    For the case of the original code from this Thread, effectively a code line like Dim WithEvents WsMe As Excel.Application and a routine like Sub InstantiateWsMe() were effectively done for us, and we had part of the main code like this in each worksheet code object module:
    Code:
    Sub WsMe_SheetChange(ByVal Sh As Object, ByVal Target As Range)
        If Sh.Name = Me.Name Then
    
        Else '
        End If
    End Sub
    The above could be considered as what is behind the following in a worksheet code module, and so is a direct equivalent to it:
    Code:
    Private Sub Worksheet_Change(ByVal Target As Range)
    
    End Sub

    It is not clear if any coding is shared in the application events and the normal events: Although a direct comparison was demonstrated in this thread with the routines, Sub WsMe_SheetChange(ByVal Sh As Object, ByVal Target As Range) and Private Sub Worksheet_SelectionChange(ByVal Target As Range) , I don’t think you can do everything with the application events that you can with the normal events. I expect some coding is shared, and , as shown, in some cases we can come close to duplicating normal event codes with application event codes.


    _.________________-

    Just to summarise: This “standard” events routine , which one may become familiar with at an early stage in learning VBA …._
    Code:
    Private Sub Worksheet_Change(ByVal Target As Range)
    
    ‘ We add codeiX here
    
    End Sub
    _.... can be considered as equivalent to Excel having already “done and run**” something like this “application event” coding: ( ** Sub InstantiateWsMe() mist have been run at least once )
    Code:
    Dim WithEvents WsMe As Excel.Application
    Sub InstantiateWsMe() 
     Set WsMe = Excel.Application 
    End Sub
    Sub WsMe_SheetChange(ByVal Sh As Object, ByVal Target As Range)
        If Sh.Name = Me.Name Then
    
    ‘ We add codeiX here
    
        Else '
        End If
    End Sub



    That concludes the main part of the Thread on Application Events

    Summary : This is what is happening/ This is how it works:
    We made an object which we named arbitrarily WsSht_1 . This is subscribed to the event codes of the current open in front of us Excel. In one of the event routines now available to this object, or rather already there in this form:…._
    Code:
    Sub  WsSht_1_SheetChange(ByVal Sh As Object, ByVal Target As Range)
    
     End Sub
    _... we added coding so that it looks now like this:_......
    Code:
    Sub  WsSht_1_SheetChange(ByVal Sh As Object, ByVal Target As Range)
        If Sh.Name = "Sht_1" Then
           If Target.Address = "$A$1" Then MsgBox prompt:="You just changed the value in the first cell in worksheet " & Me.Name & " in the Workbook " & Me.Parent.Name
        Else '
        End If
     End Sub
    Hence after running the instantiating code to “build “ the variable we were using , ( WsSht_1 ) , “into an object” , that object will “monitor” or “watch for” changes in a sheet, and take the action determine by our added coding.


    The next posts have a few relevant further things which I may add to from time to time. In particular, we will do the same in a slightly different way, the “Class” way
    Last edited by DocAElstein; 01-02-2021 at 11:01 PM.
    ….If you are my competitor, I will try all I can to beat you. But if I do, I will not belittle you. I will Salute you, because without you, I am nothing.
    If you are my enemy, we will try to kick the fucking shit out of you…..
    Winston Churchill, 1939
    Save your Forum..._
    _...KILL A MODERATOR!!

  4. #4
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,455
    Rep Power
    10
    Event coding in Excel spreadsheets(Application Events) Misc

    Post 4: “Class events” Using the “Class way” to do it

    There are a couple of pre subscribed and pre Instantiated event code added to a “Class module” after we insert a Class module.
    They basically kick in when an object is built ( instantiated ) using the blueprint of the Class and when an object from the Class is Set to Nothing
    A good way to understand their use which also helps understand the encapsulation, Encapsturbation , ideas, as well as the general use of Classes, particularly with even codes, is to consider re writing the event codes example of the last post in the way more preferred by computer professionals.
    The main difference in the two ways we will see is that we use one of the two pre subscribed and pre Instantiated event, and must then also do some other things to cause it to kick off. ( We will see that we cannot easily set this code off directly )
    Here is that code again, ( slightly modified to allow it to go in any object code module).
    The code assumes you have a worksheet with tab name “Sht_1”. If you change the value in the first cell of that worksheet, “Sht_1” , then you will get a message.

    Points to remember:…_
    _.. You must run the routine to instantiate WsSht_1 ( Sub InstantiateWsSht_1() in last post ) once to instantiate the object WsSht_1
    _.. There is no significance to the underscore, _ , in Sht_1 or WsSht_1 etc.. These are names we can choose. But as we have learnt, there is a significance to the _ and the SheetChange combination in _SheetChange , as this is a reserved events code character combination )
    Events _SheetChange Worksheet change.jpg : http://i.imgur.com/6NY0WeC.jpg
    Code:
    Dim WithEvents  WsSht_1 As Excel.Application
    Sub Instantiate____() ' Routine to Instantiate WsSht_1
     Set WsSht_1 = Excel.Application
    End Sub
    Sub WsSht_1_SheetChange(ByVal Sh As Object, ByVal Target As Range)
     If Sh.Name = "Sht_1" Then
     If Target.Address = "$A$1" Then MsgBox prompt:="You just changed the value in the first cell in worksheet """ & ActiveSheet.Name & """ in the Workbook """ & ActiveSheet.Parent.Name & """"
     Else '
     End If
    End Sub

    Summary : This is generally what we want:
    We want to make an object which we will name arbitrarily WsSht_1 . This is to be subscribed to the event codes of the current “open in front of us” Excel. In one of the event routines then available to this object, or rather already then there in this form:…._
    Code:
    Sub  WsSht_1_SheetChange(ByVal Sh As Object, ByVal Target As Range)
    
     End Sub
    _... we will add coding so that it looks now like this:_......
    Code:
    Sub  WsSht_1_SheetChange(ByVal Sh As Object, ByVal Target As Range)
       If Sh.Name = "Sht_1" Then
         If Target.Address = "$A$1" Then MsgBox prompt:="You just changed the value in the first cell in worksheet " & Me.Name & " in the Workbook " & Me.Parent.Name
       Else '
       End If
    End Sub
    Hence after running the instantiating code to “build “ the variable ( WsSht_1 ) , “into an object” , that object will “monitor” or “watch for” changes in a sheet, and take the action determine by our added coding.


    _.___
    Last edited by DocAElstein; 01-02-2021 at 10:51 PM.
    ….If you are my competitor, I will try all I can to beat you. But if I do, I will not belittle you. I will Salute you, because without you, I am nothing.
    If you are my enemy, we will try to kick the fucking shit out of you…..
    Winston Churchill, 1939
    Save your Forum..._
    _...KILL A MODERATOR!!

  5. #5
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,455
    Rep Power
    10
    (Post 5 Part 4b)
    Using the “Class way” to do it”
    The “Professional Obfuscation“ Class way to do it

    From the last Post:
    Summary ( again ) : This is generally what we want:
    We want an object which we name arbitrarily WsSht_1 . This is to be subscribed to the event codes of the “current open in front of us” Excel. In one of the event routines then available to this object, or rather already then there in this form:…._
    Code:
    Sub  WsSht_1_SheetChange(ByVal Sh As Object, ByVal Target As Range)
    
     End Sub
    _... we will be adding coding so that it looks then like this:_......
    Code:
    Sub  WsSht_1_SheetChange(ByVal Sh As Object, ByVal Target As Range)
       If Sh.Name = "Sht_1" Then
          If Target.Address = "$A$1" Then MsgBox prompt:="You just changed the value in the first cell in worksheet " & Me.Name & " in the Workbook " & Me.Parent.Name
       Else '
       End If
    End Sub
    Hence after running the instantiating code to “build “ the variable ( WsSht_1 ) , “into an object” , that object will “monitor” or “watch for” changes in a sheet, and take the action determine by our added coding.



    So now we will do the equivalent coding which is more typically done by professionals to do the same as that coding.
    First a Class module is added and its name changed to , say, Custom_WsChange. This name, including the underscore, _ , is of arbitrary choice. Right mouse click in VB Explorer Insert Class Module.JPG : http://imgur.com/1X1APHk.jpg

    The coding we put in this new Class module almost identical to that from the previous post.
    Class Custom_WsChange.JPG : http://i.imgur.com/GemN8yw.jpg
    Class : _ Custom_WsChange http://i.imgur.com/1ldUusp.jpg
    Code:
    Dim WithEvents  WsSht_1 As Excel.Application
    Private Sub Class_Initialize() ' Routine to Instantiate WsSht_1  
     Set WsSht_1 = Excel.Application
    End Sub
    Sub WsSht_1_SheetChange(ByVal Sh As Object, ByVal Target As Range)
     If Sh.Name = "Sht_1" Then
     If Target.Address = "$A$1" Then MsgBox prompt:="You just changed the value in the first cell in worksheet """ & ActiveSheet.Name & """ in the Workbook """ & ActiveSheet.Parent.Name & """"
     Else '
     End If
    End Sub
    The only difference is that the instantiate routine, ( Sub InstantiateWsSht_1() from the last post ) , is now in one of the two available pre subscribed and pre instantiated event code of Class Class Initialize.JPG : http://i.imgur.com/v5mKWhE.jpg
    Code:
    Private Sub Class_Initialize()
    
     End Sub
    At this stage we have the main equivalent coding to previously.
    In the previous coding we needed to run Sub InstantiateWsSht_1().
    The immediately obvious requirement now would be to run the equivalent Sub Class_Initialize()
    But now we cannot run ourselves Private Sub Class_Initialize() : We cannot run directly any coding in the Class : The coding in the Class module that we can see, is effectively part the internally held “blue print” instruction information used to build objects from / of that Class . The information defines what is in an object made from that Class.
    The key to getting this working is in building an object from this Class, Custom_WsChange. That may not be immediate obvious, but it will become apparent why later.

    Build the “watcher “ object, WsSht_1 in the “Class way”
    In any normal code module or object code module, we need to write the code lines to build an object of class Custom_WsChange
    The first part of this will be to declare ( Dim ) a variable to the type of Class Custom_WsChange.
    ( One notes that intellisense will now offer us our newly made Class PrivateWatcher.JPG : http://i.imgur.com/5CTnREW.jpg )
    Syntaxly, the Dim can go inside a routine , but it would not be much use as a variable for an object subscribing to events, and therefore “watching for”, as it would cease to exist at the end of a the routine. To go with this Dim , we need the some way to instantiate the object, ( “build it”).
    This coding will do on any normal or object module
    Watcher.JPG : http://i.imgur.com/fBFc5LE.jpg
    Code:
    Private Watcher As Custom_WsChange
    Sub InstantiateWsSht_1()' Routine to Instantiate Watcher  and thereby indirectly Instantiate WsSht_1  
     Set Watcher = New Custom_WsChange
    End Sub
    So that routine will need to be run once. I give it , ( by my choice ) , the same name as the (only) instantiating routine from the previous “non class way” , Sub InstantiateWsSht_1(). I do this because that is what it in effect finally does: This routine actually instantiates the object Watcher . That causes the routine in the Class module Private Sub Class_Initialize() to kick in. This is the action we can no longer do ourselves. This action is the main action that the “Class” is doing in the case of the this “Class way” of doing it”
    Once this has taken place, we are where we were with the “not using Class way” :
    Just to explain again: Here we build an object ( Watcher ) of Class Custom_WsChange . As this “comes into life” , its Sub Class_Initialize() event code builds the object WsSht_1.
    ( That code , Sub WsSht_1_SheetChange(ByVal Sh As Object, ByVal Target As Range) , must be in the Class module so that it becomes part of the object made from this Class : Generally codes in here become properties/ methods of the object built from the class. As such the functionality or actual coding is in a lower object comparable to our available worksheets code modules, but we cannot see it. Anyone that knows that in more concise detail is not telling, so that’s as good an explanation as you will get.


    _.________________________

    It is worth reminding ourselves / reviewing what we have done, ( only slightly differently this time), in the “Class way”
    We are using both
    pre subscribed and pre Instantiated event code
    and
    are own event coding using Application Event coding.
    We have chosen to use a Class module for some of the coding.
    This is what is happening/ This is how it works:
    We make an object which we named arbitrarily Watcher . As this object “comes into existence” it in turn builds our object WsSht_1. This is subscribed to the event codes of the current open in front of us Excel. In one of the event routines now available to this object, or rather already there in this form:…._
    Code:
    Sub  WsSht_1_SheetChange(ByVal Sh As Object, ByVal Target As Range)
    
     End Sub
    _... we added coding so that it looks now like this:_......
    Code:
    Sub  WsSht_1_SheetChange(ByVal Sh As Object, ByVal Target As Range)
     If Sh.Name = "Sht_1" Then
     If Target.Address = "$A$1" Then MsgBox prompt:="You just changed the value in the first cell in worksheet " & Me.Name & " in the Workbook " & Me.Parent.Name
     Else '
     End If
     End Sub
    Hence after the , ( automatic this time ) running of the instantiating code to “build “ the variable we were using , ( WsSht_1 ) “into an object” , that object will “monitor” or “watch for” changes in a sheet, and take the action determine by our added coding.
    So the “Watcher” code is “there” ( “somewhere” ) as before. The slight difference to the case of previously having that code in a “see able” object code module, is that we cannot see the actual coding in the object WsSht_1 this time: What we see as the Class module which we added, is “one level back up” the OOP chain. It is the Class Custom_WsChange which determines how the object looks. But Excel just doesn’t show us the code module as it does for the objects made from Class Worksheet and ThisWorkbook . That is just the way someone at Microsoft decided to organise it.
    _......
    We are very close now to the final solution often given for such a requirement. We need to take it just one small step further now in order to reach the coding typically presented in such solutions.
    _......
    ###If we take this a small step further we finally come to the point at which we often get plunged into the deep end when using application events:
    In a typical use, the code to instantiate would be put in one of the pre subscribed and pre Instantiated event code in the ThisWorkbook code nodule.

    With so many different event codes flying around and a Class module for good measure, its not surprising that a given solution or Tutorial on this subject often confuses.

    Purely for convenience, we would typically choose the pre subscribed and pre Instantiated event code which “monitors” or “watches for” the opening of the workbook. In this particular case, that description does not suit too well. A better description would be that the following routine is more likely hard written in the opening software permanently, so that this will always be done, regardless of whether we add any coding into it or not. This latter description is also as valid as any for all event coding.
    ( To revel this code module, double click on the ThisWorkbook ( German Excel DiesesArbeitsmappe ) shown in the VBA Project Window )
    ThisWorkbook Workbook_Open.JPG : http://i.imgur.com/kWtgiu9.jpg
    Code:
    Private Sub Workbook_Open()
    
    End Sub
    So we would simply do this,
    Code:
    Private Watcher As  Custom_WsChange
    Private Sub Workbook_Open()
     Set Watcher = New Custom_WsChange
    End Sub
    We do not have to put the variable , Watcher , in this code module: it could have remained in any normal code module as a normal global variable to be accessed from anywhere. But for general tidiness, Encapsturbation , and probably sometimes for other indirect good programming reasons, it would be put near the coding which instantiates the object, Set Watcher = New Custom_WsChange

    _._______________

    A Final shortened, simplified, summary of the typical complete Class way

    The workbook is opened.
    This causes via a ThisWorkbook event code ( __Workbook_Open() ) , an object to be made from a type / Class which we have pre determined by adding a Class module and putting code in it
    That object being made from that class in turn results in another object being made which is subscribed to events of the Excel application, ( the “Excel we see in front of us” ).
    Within one of the available event codes we have added coding such that changes in a worksheet are “monitored”
    Last edited by DocAElstein; 01-03-2021 at 06:20 PM.
    ….If you are my competitor, I will try all I can to beat you. But if I do, I will not belittle you. I will Salute you, because without you, I am nothing.
    If you are my enemy, we will try to kick the fucking shit out of you…..
    Winston Churchill, 1939
    Save your Forum..._
    _...KILL A MODERATOR!!

  6. #6
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,455
    Rep Power
    10

    Walkthrough revision. No explanations

    Walkthrough revision. No explanations
    I tried hard in the last post to start at the beginning and give clear concise explanations. ( I started doing things in the simpler way, which is rarely explained anywhere***. I finally did the more advanced “class way”).
    Inevitably it turned into a long Blog, and it is easy to get confused, especially as my approach does not tie up with most other Blogs on the subject.
    In this post I will try to avoid as much explanation as possible, and concentrate on walking through the same example again that I have used throughout. I will do it in the 2(4) ways, giving finally a workbook for each way. One example will be of the Class Way, and three will be of the Non Class Way.
    I will start with the more advanced way, the class way. ( In most Blogs that is the only way shown*** ).
    I will then do 3 examples of the simple ( non class ) way
    I will assume I want the thing to be up and running automatically as soon as I open the workbook. ( So this means that in all example I will have to make some use of the already as standard available Private Sub Workbook_Open() which can be got at via the drop down lists in the ThisWorkbook object code module
    ThisWorkbook Workbook_Open.jpg : http://i.imgur.com/10Bp8Wp.jpg , http://i.imgur.com/P6TE7uf.jpg


    What do we want.. / the previous example
    The example previously considered want to do something similar to this standard already available event macro.
    Code:
    Private Sub Worksheet_Change(ByVal Target As Range)
        If Target.Address = "$A$1" Then MsgBox prompt:="You just changed the value in the first cell in worksheet " & Me.Name & " in the Workbook " & Me.Parent.Name
    End Sub
    
    I want to do this , purely as an example, using the WithEvents of Excel.Application ideas of this Thread


    The Class way

    In the Class way we make a blue print of the coding type we need. This needs to be in a class module. ( We wont actually get to see the coding copy finally used)
    Insert a Class module , and give it some arbitrary name
    InsertAClassModule.JPG , NameAClassModule.JPG
    http://i.imgur.com/Op5rhAV.jpg , http://i.imgur.com/Cxx7nxZ.jpg
    We need the three main code parts in this class module:
    _ the dimming with events of an arbitrary named variable;
    _ the instantiating of that variable;
    _ the event coding.
    Class Custom_WsChange.JPG : http://i.imgur.com/GemN8yw.jpg
    Class : _ Custom_WsChange http://i.imgur.com/dZgJ5M7.jpg http://i.imgur.com/1ldUusp.jpg
    Code:
    Dim WithEvents  WsSht_1 As Excel.Application
    Private Sub Class_Initialize() ' Routine to Instantiate WsSht_1  
     Set WsSht_1 = Excel.Application
    End Sub
    Sub WsSht_1_SheetChange(ByVal Sh As Object, ByVal Target As Range)
     If Sh.Name = "Sheet1" Then
     If Target.Address = "$A$1" Then MsgBox prompt:="You just changed the value in the first cell in worksheet """ & ActiveSheet.Name & """ in the Workbook """ & ActiveSheet.Parent.Name & """"
     Else '
     End If
    End Sub
    We cant use / run any of those macros, because they are just a Blue Print of coding to be made. The way that class things work is that when we instantiate a variable , that is to say Set it to being of the class, then effectively we get a “real” set of the macros, ( although we can’t see them )
    Either
    _we can do that all in the ThisWorkbook like this
    VariableAndSetClassInThisWorksheetObjectCodeModule .JPG http://i.imgur.com/GwvKUI7.jpg
    Code:
    Private Watcher As Custom_WsChange
    Private Sub Workbook_Open()
     Set Watcher = New Custom_WsChange
    End Sub
    Or
    _ alternatively we can put the Private Watcher As Custom_WsChange in a normal code module
    VariableInNormalCodeModue SetClassInThisWorksheetObjectCodeModule.JPG : http://i.imgur.com/nSHMDe7.jpg

    By Setting the variable , Watcher , we effectively create an “invisible” copy of those macros, and at the same time the Instantiating Initialise macro is done

    ClassWay.xls https://app.box.com/s/5hkwnz9c5lvudne5b1418qukt830nd0w


    Simple ( non Class ) ways
    The instantiating done in the Class way can be thought of as having the effect of making an object and object code window ( which we cant see) containing the main macros and at the same time causing the Private Sub Class_Initialize() ' Routine to Instantiate WsSht _1 to run
    The simpler ways are possible because
    _we already have some object code windows which we do see, and which we can add the actual coding to.
    and
    _ either by design or by accident, we find that the various with event things are available and seem to “work” as if we were in the “invisible” object code module produced by the instantiating in the Class way

    We can probably come up with about half a dozen simple ways to do this, based on where various codings are put. We will consider 3 examples


    Simple ( non Class ) way. (Example 1)

    We can put the three main code parts in an existing object code module, for example in any worksheet object code module. ( It does not have to be that of the worksheet to which the coding is applied to). For example, we put the main macros in the second worksheet object cod module
    SimpleWay1MainMacros.JPG : http://i.imgur.com/REXWgek.jpg
    We see that due to the with events declaration, we have the required event macro available in the drop down lists
    SimpleWay1AvailabeEventMacrosAfterWithEventsDeclar ation.JPG : http://i.imgur.com/dOompwu.jpg
    The only minor difference is that the macro set off previously to instantiate the variable that is subscribed to the Excel application events will be a normal routine. (We will have to arrange that this macro is done).
    Code:
    Dim WithEvents WsSht_1 As Excel.Application
    Public Sub WsSht_1_InitializeIt() ' Routine to Instantiate WsSht_1
     Set WsSht_1 = Excel.Application
    End Sub
    Sub WsSht_1_SheetChange(ByVal Sh As Object, ByVal Target As Range)
        If Sh.Name = "Sheet1" Then
        If Target.Address = "$A$1" Then MsgBox prompt:="You just changed the value in the first cell in worksheet """ & ActiveSheet.Name & """ in the Workbook """ & ActiveSheet.Parent.Name & """"
        Else '
        End If
    End Sub
    We no longer need any variable to be set to that of any class. Instead we effectively short circuit that step, and the Workbook_Open macro inside the ThisWorkbook object code module , Calls directly the actual macro Sub WsSht_1_InitializeIt().
    Note: we need to add the object having the coding to the Call:
    CallInstanciateSimpleWay1.JPG http://i.imgur.com/EDWm5rS.jpg
    Code:
    Private Sub Workbook_Open()
     Call Worksheets("Sheet2").WsSht_1_InitializeIt
    End Sub
    SimpleNonClassWay1 : https://app.box.com/s/naxfwg3ms8omvpcybrjpzjdw3o7i4w36


    Simple ( non Class ) way. (Example 2)

    This is a minor variation on the last way.
    We can put the Sub WsSht_1_InitializeIt() instantiating macro in a normal code module.
    The Workbook_Open macro inside the ThisWorkbook object code module remains similar , ( assuming we still use the same procedure name, WsSht_1_InitializeIt() )
    We can either omit the object before the macro name, or replace it with the name of the normal code module.
    SimpleWay2ThisWorkbookObjectCodeModule.JPG http://i.imgur.com/wyLsCjq.jpg
    Code:
    Private Sub Workbook_Open()
     'Call WsSht_1_InitializeIt
     ' or
     Call Modul1.WsSht_1_InitializeIt
    End Sub
    We will need to make two other small but important changes:
    _ in the object code module containing the with events declaration: We must change Dim WithEvents WsSht_1 As Excel.Application to Public WithEvents WsSht_1 As Excel.Application
    SimpleWay2ObjectCodeModule.JPG http://i.imgur.com/gq4OJuE.jpg
    Code:
    Public WithEvents WsSht_1 As Excel.Application
    Sub WsSht_1_SheetChange(ByVal Sh As Object, ByVal Target As Range)
        If Sh.Name = "Sheet1" Then
        If Target.Address = "$A$1" Then MsgBox prompt:="You just changed the value in the first cell in worksheet """ & ActiveSheet.Name & """ in the Workbook """ & ActiveSheet.Parent.Name & """"
        Else '
        End If
    End Sub
    _ That last change above will let the variable be referenced outside of the object code module in which it is. We then need the minor modification to the instantiating macro in the normal code module so that it refers to the object:
    SimpleWay2NormalCodeModule.jpg : http://i.imgur.com/rxpZXDk.jpg
    Code:
    Sub WsSht_1_InitializeIt() ' Routine to Instantiate WsSht_1
    ' Set Worksheets("Sheet2").WsSht_1 = Excel.Application
    ' or
     Set Sheet2.WsSht_1 = Excel.Application
    End Sub

    SimpleNonClassWay2 : https://app.box.com/s/l1dtodagtappmdffagm4ktedo1qzgh2c


    Simple ( non Class ) way. ( Example 3 )
    ( Everything in the ThisWorkbook object code module )
    This is probably the simplest way.
    We use the ThisWorkbook object code module for all the main macros. The Instantiate macro is the Workbook_Open macro
    AllMacrosInThisWorkbookObjectCodeModule.JPG http://i.imgur.com/2fzKaAC.jpg
    Code:
    Public WithEvents WsSht_1 As Excel.Application
    Private Sub Workbook_Open() ' Routine to Instantiate WsSht_1
     Set WsSht_1 = Excel.Application
    End Sub
    Sub WsSht_1_SheetChange(ByVal Sh As Object, ByVal Target As Range)
        If Sh.Name = "Sheet1" Then
        If Target.Address = "$A$1" Then MsgBox prompt:="You just changed the value in the first cell in worksheet """ & ActiveSheet.Name & """ in the Workbook """ & ActiveSheet.Parent.Name & """"
        Else '
        End If
    End Sub
    We need no other macros anywhere!
    SimpleNonClassWay3(AllCodingInThisWorkbookObjectCo deModule) : https://app.box.com/s/rya16vhhyigg7466l6z1v2iudvbpcliz
    Last edited by DocAElstein; 01-07-2021 at 02:41 PM.

  7. #7
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,455
    Rep Power
    10

    Another Short Example

    Another Short Example

    Taken from this Blog post . https://www.exceltip.com/events-in-v...excel-vba.html
    https://www.exceltip.com/events-in-v...#comment-50479

    This example will bring up a message box telling you which worksheet you selected
    05_ExcelTipExampleGig.jpg
    http://i.imgur.com/rNaYcFr.gif

    http://www.exceltip.com/wp-content/u...01/gif8-13.gif

    I will do the example assuming we want the macro to be enabled by the opening of the workbook. I will do just one possible version of the Class way and the Non Class way

    Class Way

    In the ThisWorkbook object code module:
    ClassWayExTipsThisWorkbookObjectCodeModule.JPG http://i.imgur.com/gxH1KEu.jpg

    Code:
    Private AppE As MyAppEvents
    Private Sub Workbook_Open()
     Set AppE = New MyAppEvents
    End Sub
    In a Class Module, which is given the name MyAppEvents
    ClassWayExTipsThisWorkbookClassCodeModule.JPG http://i.imgur.com/Iychi2a.jpg

    Code:
    Private WithEvents myApp As Excel.Application
    Private Sub Class_Initialize()
     Set myApp = Excel.Application
    End Sub
    Private Sub myApp_SheetActivate(ByVal Sh As Object)
     MsgBox ActiveWorkbook.Name & "-" & Sh.Name
    End Sub
    ClassWayExcelTipExample.xls : https://app.box.com/s/rb7f51emtsamv18pklz358ux6cyozfkl


    Non Class Way

    In the ThisWorkbook object code module:
    NonClasWayExTipsThisWorkbookObjectCodeModule.JPG http://i.imgur.com/l9SfDDV.jpg

    Code:
    Private WithEvents myApp As Excel.Application
    Private Sub Class_Initialize()
     Set myApp = Excel.Application
    End Sub
    Private Sub myApp_SheetActivate(ByVal Sh As Object)
     MsgBox ActiveWorkbook.Name & "-" & Sh.Name
    End Sub
    NonClassWayExcelTipExample.xls : https://app.box.com/s/hllpmw3h9p277rgs6mi2321u47k2uhtb
    Attached Files Attached Files
    Last edited by DocAElstein; 01-04-2021 at 06:56 PM.

  8. #8
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,455
    Rep Power
    10

    Disable Excel Close Button/ Control closing

    Further working examples

    Disable Excel Close Button/ Control closing
    ( Post 8 )
    Part #5 Disable Excel Close Button/ Control closing Cancel option Event code example
    We can do another example as a solution to a question to “Disable Excel Close Button”. This is a good example of using an Event routine which has the Cancel option available

    Part #5A Using “normal event routines” or “standard available event routines
    Event routines of the kind required for controlling Workbook events can typically be “found” from a group which we can find in the ThisWorkbook code module
    So
    Double-click ThisWorkbook to open its code module: then you can write in manually, or better still, evoke from the drop down lists a “Workbook procedure” with the name: Private Sub Workbook_BeforeClose(Cancel As Boolean )
    Evoke a Private Sub Workbook_BeforeClose(Cancel As Boolean).JPG : https://imgur.com/T7w6FJN , https://imgur.com/J22uX3g
    Code:
    Private Sub Workbook_BeforeClose(Cancel As Boolean)
      ' here we can add code to this “already available to us” event coding. Effectively the workbook was Dimed WithEvents somehow to the hidden class or similar of the Workbook object which is effectively also already effectively instantiated as we "open" the Workbook
    End Sub
    I am thinking that in such a code ….. the code has a secret hidden coding at the end which you can’t see. It really looks, pseudo, like this:
    Code:
    Private Sub Workbook_BeforeClose(Cancel As Boolean)
    
    ' here we can add code to this “already available to us” event coding. Effectively the workbook was Dimed WithEvents somehow to the hidden class or similar of the Workbook object which is effectively also already effectively instantiated as we "open" the Workbook
    
    ' Secret code section not visible to us
        If Cancel = True Then
         'Do nothing and Exit this sub
        ElseIf Cancel = False Then
         'Close this workbook
        End If
    End Sub
    So a solution , such as here http://www.eileenslounge.com/viewtopic.php?f=27&t=31331 , is to give you a way to have the default value of Cancel set to True within that code Private Sub Workbook_BeforeClose(Cancel As Boolean ) . ( I assume that the usual default value of Cancel will be False ).
    So, as in that post, we add coding in that event procedure which will make Cancel True by default. This will result in the , Private Sub Workbook_BeforeClose(Cancel As Boolean ) preventing a close of the workbook.
    For example, assume we have some global Boolean variable, CanClose , which by default will be False , (False is the default state for a Boolean Variable )
    Then we add a code line to the event routine:
    Code:
    Private Sub Workbook_BeforeClose(Cancel As Boolean)
     Let Cancel = Not CanClose '  With CanClose = True,  Cancel will be set to Not True = False
    
    ' Secret code section not visible to us
        If Cancel = True Then
         'Do nothing and Exit this sub
        ElseIf Cancel = False Then
         'Close this workbook
        End If
    End Sub
    The above coding will mean that if we do nothing else, Cancel will be set to True. So in normal use, such as by the user hitting the close button top right , Excel Close Button.JPG: https://imgur.com/ZvQCF2q , that procedure will prevent/cancel the closing.
    Then we could make a procedure, Sub CloseMe() , to be put in a normal module , _..
    Code:
    Public CanClose As Boolean ' This will be False by default
    
    
    Sub CloseMe()
     Let CanClose = True
     ThisWorkbook.Close
     Let CanClose = False ' I don't know why this is here? I don't think it will ever be done!!! ???
    End Sub
    _... This will allow you to change the value of Cancel to True: It works as follows: If that procedure, Sub CloseMe(), is run, then it changes the global variable, CanClose , to True, and then the next line, _..
    ThisWorkbook.Close
    _.. cause the code, Private Sub Workbook_BeforeClose(Cancel As Boolean) to start, and with CanClose equal to True, Cancel being set to Not CanClose , will be set to its usual value of False, and the workbook will close as usual.


    That all makes sense, I think.
    _._________________________________


    In the next post, I will do the equivalent with “application events way” in the typical “class / application way” that is typically done. As was discussed in previous posts, this is a slightly less direct way then necessary, but which is preferred for reasons of good programming practice.
    Last edited by DocAElstein; 01-04-2021 at 02:47 AM.
    ….If you are my competitor, I will try all I can to beat you. But if I do, I will not belittle you. I will Salute you, because without you, I am nothing.
    If you are my enemy, we will try to kick the fucking shit out of you…..
    Winston Churchill, 1939
    Save your Forum..._
    _...KILL A MODERATOR!!

  9. #9
    Fuhrer, Vierte Reich DocAElstein's Avatar
    Join Date
    Aug 2014
    Posts
    9,455
    Rep Power
    10
    ( Post 9 )
    Part #5B Using “ application events way ” in the typical “class / application way
    Brief description:
    As seen in the previous posts, it is very easy to get lost, so it is good to summarise in simple terms what we are going to do:
    We use two “standard available event routines” and one “application events routine
    And we build two objects, or rather, we build one new object, and just assign a new variable to an existing object for the second one.
    We do a somewhat round about way, more complicated than necessary, as there seems to be some good programming reason for organising things like this in that way.
    The standard available event routine which kicks in when the workbook is opened is used. This “builds” the first of two object, in this case, a non standard object from a type (Class). The “blue print” of that type we prepare earlier. This “blue print” information is determined ( written ) inside a Class module which we add. That Class thing has a standard available event routine in it, which is the second standard available event routine thing which we use. That second standard available event routine kicks in when the first object, an object from that type/class is built. We add coding within that event routine to assign an object variable to a second object. That second object is the main object we need. So effectively, the first object being built causes that second object to be built, or rather in this case of the second object, the variable is assigned to an existing object: The variable for that object is declared to the type which is the Excel application itself. In other words, the variable we use for that object is Dimed to the Excel thing we have in front of us. But it is Dimed in a special way, like “Dim WithEvents” . This means that we then have some extra non standard available event coding available to us, which will be the event routines of the type of object ( class) to which we Dim/declare. In this case we Dim/declare to the Excel application itself, and so our new variable has access to the event routines of our Excel application itself.
    We choose to use the event routine that “monitors” workbooks being closed. The coding for that we write in the class module. So that becomes part of the second object. So once that object is built/ assigned it has that coding in it. We add in that routine the coding to determine what is done when a workbook is closed.

    Full Description and process
    Open the VB development window, for example using keys Alt+F8 when you have an Excel Application up and running in front of you.
    We insert a new Class module thing: Right click anywhere in the VBA Project window and select to insert a Class module. As we want to declare ( Dim ) to this type, it would be useful to give it a different name.
    Right Click in VBA Project window Insert Class module Rename.JPG : https://imgur.com/ZUJGnS4
    For example, in line with the reference I am using ( https://stackoverflow.com/questions/...ng-of-workbook ) I choose the name CloseHelper
    In this class code module we need the main ( second ) object which we want , which refers to the open Excel application in front of us. Lets use the variable , ClsLisWb , for this object. It is intended that this object “monitors closing of workbooks.
    From the first post of this thread ( http://www.excelfox.com/forum/showth...ll=1#post10854 ) we know that we do not want to instantiate using Set ClsLisWb = New Excel.Application , as we want to use the existing Excel open in front of us, so we add the single code line , Set ClsLisWb = Excel.Application , to the Initialize routine, which is typically the first event routine which is offered to us from the drop down list in a newly added Class module, Class Initialize Event.JPG : https://imgur.com/CC5XZOB
    The object, ClsLisWb , made by the Class initialize code is that which we want to “monitor” closing of workbooks. In the current way of doing things, the Class module effectively has written in it the blue print instructions for the object and sub objects of it, ( in this case ClsLisWb is an under object / sub object “belonging” to the parent object . ( I will arbitrarily name the first object , LisExcelLike ).
    I will add here in the Class module an event routine which is now available to ClsLisWb . We look for one which monitors workbook closing and find this one: , Private Sub ClsLisWb_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean) , WorkbookBeforeClose.JPG : https://imgur.com/xVFWMmL
    After the object ClsLisWb is “built/assigned”, then this routine will effectively be a method of ClsLisWb which automatically starts on a Workbook close event taking place.
    So complete coding such as the following , within the Class module , will partially fulfil our requirements:
    CloseHelper.JPG : https://imgur.com/kt46yRn
    Class module CloseHelper
    Code:
    Option Explicit
    Private WithEvents ClsLisWb As Excel.Application
    Private Sub Class_Initialize() ' ' Routine to Instantiate ClsLisWb
     Set ClsLisWb = Excel.Application '
    End Sub
    Private Sub ClsLisWb_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
     Let Cancel = Not CunCls  '  With CanClose = True,  Cancel will be set to Not True = False
        If Not Wb Is ThisWorkbook Then Let Cancel = False 'To allow normal closing for other workbooks
    ' Secret code section not visible to us
        If Cancel = True Then
         'Do nothing and Exit this sub
        ElseIf Cancel = False Then
         'Close the workbook, Wb
        End If
    End Sub
    The small additional added coding from us above is similar to that from the last post, except that it includes an extra line so as to restrict the control of the closing to a particular workbook. ( To keep the example similar to the previous post, the closing control is restricted to the workbook in which the code is. ( we did not need that in the previous post ,as the corresponding event routine used , a standard one in that case, only applied to the workbook in which the routine was in. ) ).

    So we have the class module part of our solution.
    We would typically for convenience include the code to build the object LisExcelLike in the standard available event routine in the ThisWorkbook code module:
    ThisWorkbook code module
    Code:
    Private LisExcelLike As CloseHelper
    Private Sub Workbook_Open()
     Set LisExcelLike = New CloseHelper
    End Sub
    That code will kick off automatically when the workbook is opened.
    Just to remind ourselves again of what goes on: The instantiating of LisExcelLike happens then automatically when the workbook is opened, which in turn results in the instantiating, or rather assignnng, of the main object of interest to us, the second object, ClsLisWb

    Finally, as in the previous post example, we have a simple code in a normal code module to allow us to overwrite the close workbook prevention.
    Normal Code module
    Code:
    Option Explicit
    Public CunCls As Boolean
    Sub CloseMe()
     Let CunCls = True
     ThisWorkbook.Close
     Let CunCls = False ' I don't know why this is here? I don't think it will ever be done!!! ???
    End Sub






    Rem Ref
    ' ‘ http://www.eileenslounge.com/viewtopic.php?f=27&t=31331
    ' https://stackoverflow.com/questions/...ng-of-workbook
    Last edited by DocAElstein; 01-04-2021 at 02:48 AM.
    ….If you are my competitor, I will try all I can to beat you. But if I do, I will not belittle you. I will Salute you, because without you, I am nothing.
    If you are my enemy, we will try to kick the fucking shit out of you…..
    Winston Churchill, 1939
    Save your Forum..._
    _...KILL A MODERATOR!!

Similar Threads

  1. How To Create Interactive Charts in Excel Using Chart Events
    By Transformer in forum Tips, Tricks & Downloads (No Questions)
    Replies: 2
    Last Post: 04-18-2019, 03:32 PM
  2. Replies: 1
    Last Post: 09-29-2013, 12:02 AM
  3. Replies: 4
    Last Post: 07-10-2013, 04:35 AM
  4. Replies: 1
    Last Post: 02-14-2013, 11:08 AM
  5. Excel Application.OnKey With Parameter
    By Excel Fox in forum Excel Help
    Replies: 0
    Last Post: 11-29-2011, 01:31 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •