首页 文章

Excel VBA - 始终在打开时显示工作表

提问于
浏览
4

如何使用VBA代码满足以下条件?

  • 特定工作表始终显示在打开状态,即使在未启用宏的情况下打开工具簿也是如此 .

  • 工作簿用户可以在处理任何工作表时保存工作簿 .

  • 保存不得干扰用户 - 不导航到不同的工作表,没有消息框等 .

  • 常规保存功能(Ctrl-S,单击保存)必须保持可用,使用时必须遵守上述条件 .

我想避免在本问题的底部列出的尝试解决方案 .

Details:
该工作簿是在Windows 7计算机上使用Office 2007创建的 . 它是一个包含2个工作表的.xlsm工作簿,"Scheduler"和"Info."工作表标签不可见 . 并非所有用户都会在打开工作簿时启用宏 .

打开工作簿后,用户将只能看到如下所示的一个工作表:

如果宏被禁用,则显示

  • "Info",并且基本上告诉任何打开工作簿的人需要为完整工作簿功能启用宏 . 如果此时启用了宏,则会激活"Scheduler" .

  • "Scheduler"是存储和编辑数据的位置,如果启用了宏,则会自动显示 . 在未启用宏的情况下打开工作簿时,不会向用户显示该内容 .

如果打开工作簿并禁用宏,则“Info”必须首先显示 .

Attempted Solutions (我正在寻找更好的解决方案!):

  • Workbook.BeforeSave 事件中放置代码 . 这样可以保存"Info"激活,以便在打开工作簿时显示 . 但是,如果用户在"Scheduler"并且没有完成,我在此事件中找不到保存后重新激活"Scheduler"的方法 .

  • 使用 Application.OnKey 重新映射Ctrl-s和Ctrl-S键击 . 不幸的是,这省去了使用鼠标保存的用户(单击文件...保存或Office按钮...保存) .

  • 在每个操作期间检查,如果需要,则激活"Scheduler" . 换句话说,在 Workbook.SheetActivate.SheetChange 事件之类的内容中插入代码,以便在激活"Info"保存后将"Scheduler"重新置于焦点 . 这会不断地运行VBA代码并且让我觉得这是让工作簿中的其他代码陷入麻烦的好方法 .

  • Worksheet("Info").Activate 事件中放置代码,将焦点更改回"Scheduler" . 这导致"Scheduler"的结果,而不是"Info",显示工作簿打开时,即使禁用了宏 .

5 回答

  • 5

    我没有时间对此进行测试,但您可以在BeforeSave事件处理程序中使用 Application.OnTime 来执行此操作 . 就像是:

    Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
        Dim objActiveSheet
        Set objActiveSheet = Me.ActiveSheet
        If objActiveSheet Is InfoSheet Then Exit Sub
        If Module1.PreviousSheet Is Nothing Then
            Set Module1.PreviousSheet = objActiveSheet
            InfoSheet.Activate
            Application.OnTime Now, "ActivatePreviousSheet"
        End If
    End Sub
    

    然后在Module1中:

    Public PreviousSheet As Worksheet
    
    Public Sub ActivatePreviousSheet()
        If Not PreviousSheet Is Nothing Then
            PreviousSheet.Activate
            Set PreviousSheet = Nothing
        End If
    End Sub
    
  • 4

    这不行吗? Updated to handle Saving gracefully

    Private Sub Workbook_Open()
        ThisWorkbook.Worksheets("Scheduler").Activate
    End Sub
    
    Private Sub Workbook_BeforeClose(Cancel As Boolean)
        ThisWorkbook.Worksheets("Info").Activate
        If (ShouldSaveBeforeClose()) Then
            Me.Save
        Else
            Me.Saved = True ' Prevents Excel Save prompt.
        End If
    End Sub
    
    Private Function ShouldSaveBeforeClose() As Boolean
        Dim workbookDirty As Boolean
        workbookDirty = (Not Me.Saved)
        If (Not workbookDirty) Then
            ShouldSaveBeforeClose= False
            Exit Function
        End If
    
        Dim response As Integer
        response = MsgBox("Save changes to WorkBook?", vbYesNo, "Attention")
        ShouldSaveBeforeClose= (response = VbMsgBoxResult.vbYes)
    End Function
    
  • 1

    编辑2:这是一个不使用AfterSave的重写 . 您可能需要根据需要调整从GetSaveAsFilename创建的对话框 .

    这取决于覆盖默认保存行为并自行处理保存 .

    Private actSheet As Worksheet
    Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
        Cancel = True
        PrepareForSave
        manualSave SaveAsUI
        AfterSave ThisWorkbook.Saved
    End Sub
    Private Sub PrepareForSave()
        Set actSheet = ThisWorkbook.ActiveSheet
        ThisWorkbook.Sheets("Info").Activate
        hidesheets
    End Sub
    Private Sub manualSave(ByVal SaveAsUI As Boolean)
        On Error GoTo SaveError 'To catch failed save as
        Application.EnableEvents = False
        If SaveAsUI Then
            If Val(Application.Version) >= 12 Then
                sPathname = Application.GetSaveAsFilename(FileFilter:="Excel Files (*.xlsm), *.xlsm")
                If sPathname = False Then 'User hit Cancel
                    GoTo CleanUp
                End If
                ThisWorkbook.SaveAs Filename:=sPathname, FileFormat:=52
            Else
                sPathname = Application.GetSaveAsFilename(FileFilter:="Excel Files (*.xls), *.xls")
                If sPathname = False Then
                    GoTo CleanUp
                End If
                ThisWorkbook.SaveAs Filename:=sPathname, FileFormat:=xlNormal
            End If
        Else
            ThisWorkbook.Save
        End If
    SaveError:
        If Err.Number = 1004 Then
            'Cannot access save location
            'User clicked no to overwrite
            'Or hit cancel
        End If
    CleanUp:
        Application.EnableEvents = True
    End Sub
    
    Private Sub AfterSave(ByVal bSaved As Boolean)
        showsheets
        If actSheet Is Nothing Then
            ThisWorkbook.Sheets("Scheduler").Activate
        Else
            actSheet.Activate
            Set actSheet = Nothing
        End If
        If bSaved Then
            ThisWorkbook.Saved = True
        End If
    End Sub
    Private Sub hidesheets()
        For Each ws In ThisWorkbook.Worksheets
            If ws.Name <> "Info" Then
                ws.Visible = xlVeryHidden
            End If
        Next
    End Sub
    Private Sub showsheets()
        For Each ws In ThisWorkbook.Worksheets
            ws.Visible = True
        Next
    End Sub
    Private Sub Workbook_Open()
        AfterSave True
    End Sub
    

    在没有启用宏的情况下首先显示 Info 的唯一方法是保存工作簿的方式 . 这是保存时最合理的处理方式 .

    除非我误解了你的问题,否则不使用BeforeSave似乎是错误的 . 只要确保也使用AfterSave . 这是一个例子:

    Private actSheet As Worksheet
    Private Sub Workbook_AfterSave(ByVal Success As Boolean)
        showsheets
        actSheet.Activate
        Set actSheet = Nothing
        Thisworkbook.Saved = true 'To prevent save prompt from appearing
    End Sub
    
    Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
        Set actSheet = ThisWorkbook.activeSheet
        ThisWorkbook.Sheets("Info").Activate
        hidesheets
    End Sub
    
    Private Sub Workbook_Open()
        showsheets
        ThisWorkbook.Sheets("Scheduler").Activate
    End Sub
    Private Sub hidesheets()
        For Each ws In ThisWorkbook.Worksheets
            If ws.Name <> "Info" Then
                ws.Visible = xlVeryHidden
            End If
        Next
    End Sub
    Private Sub showsheets()
        For Each ws In ThisWorkbook.Worksheets
            ws.Visible = True
        Next
    End Sub
    

    使用私有对象actSheet允许在保存后重新选择“ActiveSheet” .

    编辑:我注意到你在评论中有更多要求 . 代码已更新,现在保存时,只有信息表可见,但在打开或保存后,每张工作表都会重新出现 .

    这使得任何打开没有宏的文件的用户都无法使用激活的不同工作表进行保存,甚至无法查看其他工作表 . 这肯定会有助于激励他们启用宏!

  • 1

    这个问题在过去已经被扼杀,很难找到真正有效的解决方案 . 看看这个代码应该做你需要的 . 基本上它显示一个启动画面,如果用户不启用宏,则隐藏所有其他工作表 . 如果用户点击保存并且不会干扰他们的工作,它仍将正常保存 . 如果他们保存并打开工作表,它将在下次打开时仍然只显示启动画面 . 下载下面的示例文件,您可以自己测试,确保下载Reafidy发布的文件,它有超过400个视图 . 如果您需要进一步修改,请告诉我 .

    Private Sub Workbook_BeforeClose(Cancel As Boolean) 
        bIsClosing = True 
    End Sub 
    Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean) 
        Dim wsArray() As Variant 
        Dim iCnt As Integer 
        Application.ScreenUpdating = 0 
    
        Splash.Visible = True 
    
        For Each wsSht In ThisWorkbook.Worksheets 
            If Not wsSht.CodeName = "Splash" Then 
                If wsSht.Visible = True Then 
                    iCnt = iCnt + 1: Redim Preserve wsArray(1 To iCnt) 
                    wsArray(iCnt) = wsSht.Name 
                End If 
                wsSht.Visible = xlSheetVeryHidden 
            End If 
        Next 
    
        Application.EnableEvents = 0 
        ThisWorkbook.Save 
        Application.EnableEvents = 1 
    
        If Not bIsClosing Then 
            For iCnt = 1 To UBound(wsArray) 
                Worksheets(wsArray(iCnt)).Visible = True 
            Next iCnt 
            Splash.Visible = False 
            Cancel = True 
        End If 
    
        Application.ScreenUpdating = 1 
    End Sub 
    Private Sub Workbook_Open() 
        Dim wsSht As Worksheet 
    
        For Each wsSht In ThisWorkbook.Worksheets 
            wsSht.Visible = xlSheetVisible 
        Next wsSht 
    
        Splash.Visible = xlSheetVeryHidden 
    
        bIsClosing = False 
    End Sub
    

    可以找到示例文件here.

  • 1

    如何使用“代理工作簿” .

    '代理工作簿'

    • 是用户直接打开的唯一工作簿

    • 包含信息表

    • 包含VBA以使用Workbook.Open打开你的'real workbook'(因为我已经检查过Workbooks.Open文档,默认情况下它不会将文件名添加到你最近的文件历史中,除非你将AddToMru参数设置为true)

    • 如果需要,VBA代码甚至可以确保您的'target workbook'是可信的(我找到了一些示例代码here

    '目标工作簿'

    • 包含您的日程表和任何其他表格
      仅当'proxy workbook'中的VBA代码被执行时才会打开

    用户可以像往常一样保存

    我没有Office 2007可以测试这个,但认为应该这样做 .

相关问题