Worksheet_Deactivate() Cannot Use Active Sheet functions

不想你离开。 提交于 2019-12-11 12:15:49

问题


I have 50 datasheets in the project, and nobody remembers to run the save macro when going to another sheet. The bright idea is to use a private sub Worksheet_Deactivate to do the necessary calculations when they select another worksheet. In addition to the 50 datasheets, there are two more worksheets in the workbook for which the calculation must not run. It would be nice if the sub could be put in "Worksheets" rather than replicated 50 times in individual worksheets, but the two other worksheets need to be excluded from processing.

Problem is, the sub defaults to the deactivating worksheet (such as an unqualified "Range.Value =" in the macro code), but the active worksheet is now the worksheet being navigated TO. So any ActiveXXXXX statement directs to the wrong worksheet. Worksheet.Name is disallowed.

Datasheets are numbered 1 to 50. What is needed is a statement early in the deactivate sub similar to

If DeactivatingWorksheet(X) = "BasicInfo" Or "Constants" Then GoTo EndSub where X is the value of the deactivating worksheet. Of course, X is known only to Excel at the moment of processing.

I can't seem to figure out how to refer to the deactivating worksheet in the macro's IF statement. Any ideas?


回答1:


Use Workbook_SheetDeactivate(ByVal sh as Object) instead of Worksheet_Deactivate(). The Workbook-level event supplies the name of the sheet being departed, even though in both cases the ActiveSheet has already changed when when event fires. Use sh just like a worksheet variable - sh.Name, sh.ProtectionMode, etc.

Now you don't need 50 subs; just one. Another thing that this allows is, you can "abort" the change to the now ActiveSheet by sh.Activate to the old one (but turn off events or you'll have a lovely infinite loop).

Me also gives the old sheetname and works for the worksheet event, if you still want to go that way. Me is the old one, ActiveSheet is the new one.




回答2:


If you are using Worksheet_Deactivate and this calls a subroutine in a seperate module, you can pass the name of the deactivating worksheet to the subroutine.

For instance, if your subroutine is something like:

Sub test()
    ActiveSheet.Range("whatever") = "something"
    ThisWorkbook.Save
End Sub

And you call it from the worksheet like:

Private Sub Worksheet_Deactivate()
    Module1.test()
End Sub

You can add a parameter to the subroutine to take the worksheet name, and add a test:

Sub test(worksheetname as string)
    If worksheetname <> "dontsavethistab" then
        ActiveSheet.Range("whatever") = "something"

        'or... you could also do:
        Sheets(worksheetName).Range("Whatever") = "something"

        ThisWorkbook.Save
    End If
End Sub

And call it from your Worksheet_Deactivate event like:

Private Sub Worksheet_Deactivate()
    Module1.test (Me.Name)
End Sub

If you wanted to get a little cleaner, instead of the worksheet name you could pass the worksheet object:

Private Sub Worksheet_Deactivate()
    Module1.test(Me)
End Sub

Sub test(ws as worksheet)
    If ws.name <> "dontsavethistab" then
        ws.Range("Whatever") = "something"    
        ThisWorkbook.Save
    End If
End Sub

This way you have the entire worksheet object to do with as you please in your subroutine.



来源:https://stackoverflow.com/questions/32261280/worksheet-deactivate-cannot-use-active-sheet-functions

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!