存档在 ‘Excel事件’ 分类中.

Excel Hacks #3:阻止用户执行某些操作

虽然Excel为工作簿和工作表提供了全面的保护,但是这种“生硬的”工具没有限制用户的“特权”,除非您使用一些技巧。
通过监控和响应事件,您能够管理电子表格与用户的交互。事件是处理工作簿和工作表时所发生的操作。一些常见的事件包括打开工作簿、保存工作簿和关闭工作簿。当触发这些事件中的任一事件时,您能告诉Excel自动执行一些VB代码。
提示:用户能够通过完全禁用宏,从而避免所有保护。单击Office按钮─—Excel选项─—信任中心─—信任中心设置,按“宏设置”按钮,如果安全性被设置为“禁用所有宏,并且不通知”,那么在打开含有宏的工作簿时将没有机会运行宏。
阻止工作簿“另存为…”
通过选择Office按钮─—保存─—工具按钮─—常规选项,然后选中“建议只读”复选框,这样可以指定任何工作簿被保存为只读。这能阻止用户对该文件保存所做的任何修改,除非将其保存为不同的名称或者在不同的位置保存该文件。
然而,有时您可能想阻止用户使用或者不使用不同的名称在另一个目录或文件夹中保存工作簿副本。换句话说,您想用户能够在现有文件中保存,而不是在其他地方保存另一个副本。当多个人对某个工作簿保存修改时,这特别方便,此时不会存在保存在不同文件夹中相同工作簿的多个副本。
自从Excel 97后,就可以使用“保存前”事件了。正如其名称所述,该事件在工作簿被保存之前发生,能够在事实发生之前捕获用户、发出警告,以及阻止Excel保存。
要插入代码,打开工作簿并选择“开发工具─—Visual Basic”,双击工程资源管理器中的ThisWorkbook,在VBE中输入下面的代码,如图1所示,然后返回工作簿,再保存工作簿:
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
    Dim lReply As Long
    If SaveAsUI = True Then
        lReply = MsgBox(”对不起,不允许您以其它名称保存本工作簿.” & _
            ”您希望保存本工作簿吗?”, vbQuestion + vbOKCancel)
        Cancel = (lReply = vbCancel)
        If Cancel = False Then Me.Save
        Cancel = True
    End If
End Sub

beforesave
图1:输入到ThisWorkbook中的代码
此时,选择“Office按 钮─—保存”,该工作簿将按预料的那样保存。然而,在选择“Office按钮─—另存为”时,Excel将通知您不能以其它的名称保存该工作簿,除非您禁用宏。
提示:当在Excel 2007中保存工作簿时,如果该工作簿包含宏或代码,那么应该将工作簿保存为启用宏的工作簿(*.xlsm),而不能保存为标准的Excel文件格式( *.xlsx)。
阻止用户打印工作簿
可能您想阻止用户打印您的工作簿,此时使用Excel的“打印前”事件。在VBE中输入下面的代码:
Private Sub Workbook_BeforePrint(Cancel As Boolean)
    Cancel = True
    MsgBox “对不起,您不能打印本工作簿.”, vbInformation
End Sub

如果希望仅阻止用户打印工作簿中特定的工作表,使用下列代码:
Private Sub Workbook_BeforePrint(Cancel As Boolean)
    Select Case ActiveSheet.Name
        Case “Sheet1″, “Sheet2″
        Cancel = True
        MsgBox “对不起,您不能打印本工作簿中的这个工作表.”, vbInformation
    End Select
End Sub

注意,您指定阻止打印工作表“Sheet1”和“Sheet2”。当然,可以修改为工作簿中的任何工作表的名称。要添加工作表,只需在代码后面加上逗号,然后在双引号中输入该工作表的名称。
阻止用户插入更多的工作表
Excel可以保护工作簿的结构以便用户不能删除工作表、重新排列它们出现的顺序、重新命名它们,等等。但是,有时希望仅阻止添加更多的工作表,而仍然允许其它的结构更改。
可以使用下列代码:
Private Sub Workbook_NewSheet(ByVal Sh As Object)
    Application.DisplayAlerts = False
    MsgBox “对不起,不能对工作簿添加任一工作表.”, vbInformation
    Sh.Delete
    Application.DisplayAlerts = True
End Sub

上述代码首先显示消息框,然后在用户单击消息框中的确定按钮后立即删除新添加的工作表。Application.DisplayAlerts = False语句的阻止标准的Excel警告,即要求用户是否想删除工作表。
另一种阻止用户添加工作表的方法是,选择“审阅─—更改─—保护工作簿”,然后按下“保护结构和窗口”。然而,正如本技巧开始所述,Excel的工作表保护是相当“生硬的”工具,它会同时阻止了许多其它的Excel功能。

注:初译自《Excel Hacks》,仅供参考。

标签: , ,

Excel快捷菜单和Excel事件

本文中的示例演示了与事件协同使用的不同的快捷菜单编程技术。
自动添加和删除菜单
如果需要在打开工作簿时修改快捷菜单,则使用Workbook_Open事件。下面的代码存储在ThisWorkbook对象的代码模块中,在打开工作簿时将执行ModifyShortcut过程。
Private Sub Workbook_Open()
    Call ModifyShortcut
End Sub

要使快捷菜单恢复到其修改前的状态,则使用下面的过程。该过程在关闭工作簿之前执行,并且会调用RestoreShortcut过程。
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    Call RestoreShortcut
End Sub

但是,这里存在着一个问题,即在用户关闭工作簿时,如果不保存该工作簿,会发生意外情况。在Workbook_BeforeClose事件处理运行之后,Excel会提示“是否保存对工作簿所作的修改?”,此时,如果用户单击“取消”按钮,则工作簿仍然保持打开,但自定义菜单已经被删除了。
对该问题的一种解决方法是绕开Excel的提示,在Workbook_BeforeClose过程中编写代码来询问用户保存该工作簿。下面的代码演示了如何进行操作:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
    If Not Me.Saved Then
        Msg = “您想保存对”
        Msg = Msg & Me.Name & “的改变吗?”
        Ans = MsgBox(Msg, vbQuestion + vbYesNoCancel)
        Select Case Ans
            Case vbYes
                Me.Save
            Case vbNo
                Me.Saved = True
            Case vbCancel
                Cancel = True
                Exit Sub
        End Select
    End If
    Call RestoreShortcut
End Sub

上述过程确定是否已保存了工作簿,如果该工作簿已保存,则没有问题,执行RestoreShortcut过程,然后关闭该工作簿。但是如果还没有保存该工作簿,则该过程显示一条复制Excel正常显示时的消息框。如果用户单击“是”,则保存工作簿,并删除菜单,然后关闭工作簿。如果用户单击“否”,则代码将Workbook对象的Saved属性设置为True(实际上没有保存该文件)并删除菜单。如果用户单击“取消”,则BeforeClose事件被取消,过程结束而不会恢复快捷菜单。

禁用或者隐藏快捷菜单项
当禁用某菜单项时,其文本显示为暗灰色的阴影,单击该菜单项时没有任何反应。当隐藏某菜单项时,在快捷菜单中不会出现该菜单项。当然,您可以编写VBA代码来启用或禁用快捷菜单项。同样,您可以编写代码来隐藏快捷菜单项。关键是要使用正确的事件。
例如,下面的代码在激活工作表Sheet2时禁用Change Case快捷菜单项(该菜单项已添加到单元格快捷菜单中,参见“使用VBA自定义Excel 2007快捷菜单”),该过程位于Sheet2代码模块中:
Private Sub Worksheet_Activate()
    CommandBars(”Cell”).Controls(”Change Case”).Enabled = False
End Sub

要在工作表Sheet2失活时(即不为当前活动工作表时)启用该菜单项,添加下面的过程。其效果是,除了激活工作表Sheet2外,Change Case菜单项在所有其它情形下均可用。
Private Sub Worksheet_Deactivate()
    CommandBars(”Cell”).Controls(”Change Case”).Enabled = True
End Sub
要隐藏该菜单项而不是禁用它,只需使用Visible属性代替Enabled属性。

创建一个上下文相关的快捷菜单
可以创建一个全新的快捷菜单,并且在响应特定的事件时显示该菜单。下面的代码创建一个名为MyShortcut的快捷菜单,包含有6个菜单项,分别设置其OnAction属性来执行简单的过程,即分别显示“单元格格式”对话框中的某一选项卡(参见下图1)。
ExcelMenuAndEvent
图1:一个新的快捷菜单,仅当用户右击工作表阴影区域中的某单元格时出现
Sub CreateShortcut()
    Dim myBar As CommandBar
    Dim myItem As CommandBarControl
    
    ‘   若已存在该菜单,则删除
    DeleteShortcut
    
    ‘   添加一个新菜单
    Set myBar = CommandBars.Add _
      (Name:=”MyShortcut”, Position:=msoBarPopup, Temporary:=True)
    
    ‘   添加一个新菜单
    Set myItem = myBar.Controls.Add(Type:=msoControlButton)
    With myItem
        .Caption = “&Number Format…”
        .OnAction = “ShowFormatNumber”
        .FaceId = 1554
    End With
        
    ‘   添加一个新菜单
    Set myItem = myBar.Controls.Add(Type:=msoControlButton)
    With myItem
        .Caption = “&Alignment…”
        .OnAction = “ShowFormatAlignment”
        .FaceId = 194
    End With
        
    ‘   添加一个新菜单
    Set myItem = myBar.Controls.Add(Type:=msoControlButton)
    With myItem
        .Caption = “&Font…”
        .OnAction = “ShowFormatFont”
        .FaceId = 309
    End With
    ‘   添加一个新菜单
    Set myItem = myBar.Controls.Add(Type:=msoControlButton)
    With myItem
        .Caption = “&Borders…”
        .OnAction = “ShowFormatBorder”
        .FaceId = 149
        .BeginGroup = True
    End With
    
    ‘   添加一个新菜单
    Set myItem = myBar.Controls.Add(Type:=msoControlButton)
    With myItem
        .Caption = “&Fill…”
        .OnAction = “ShowFormatPatterns”
        .FaceId = 687
    End With
    
    ‘   添加一个新菜单
    Set myItem = myBar.Controls.Add(Type:=msoControlButton)
    With myItem
        .Caption = “&Protection…”
        .OnAction = “ShowFormatProtection”
        .FaceId = 225
    End With
End Sub

创建了快捷菜单后,可以通过使用ShowPopup方法来显示该菜单。下面的过程,位于Worksheet对象的代码模块中,当用户右击某单元格时执行:
Private Sub Worksheet_BeforeRightClick _
  (ByVal Target As Excel.Range, Cancel As Boolean)
    If Union(Target.Range(”A1″), Range(”data”)).Address = _
      Range(”data”).Address Then
        CommandBars(”MyShortcut”).ShowPopup
        Cancel = True
    End If
End Sub

当用户右击时,如果活动单元格在名为data的单元格区域内,则显示MyShortcut菜单。设置Cancel参数为True,确保不显示正常的快捷菜单。注意,微型(mini)工具栏也没有显示。
下面是创建快捷菜单的过程代码中对应的所要执行的宏:
Sub ShowFormatNumber()
    ‘Application.Dialogs(xlDialogFormatNumber).Show
    CommandBars.ExecuteMso (”FormatCellsNumberDialog”)
End Sub
Sub ShowFormatAlignment()
    ‘Application.Dialogs(xlDialogAlignment).Show
    CommandBars.ExecuteMso (”CellAlignmentOptions”)
End Sub

Sub ShowFormatFont()
    ‘Application.Dialogs(xlDialogFormatFont).Show
    CommandBars.ExecuteMso (”FormatCellsFontDialog”)
End Sub

Sub ShowFormatBorder()
    ‘Application.Dialogs(xlDialogBorder).Show
    CommandBars.ExecuteMso (”BordersMOreDialog”)
End Sub

Sub ShowFormatPatterns()
    ‘(没有ExecuteMso方法,因此使用旧样式)
    Application.Dialogs(xlDialogPatterns).Show
End Sub

Sub ShowFormatProtection()
    ‘(没有ExecuteMso方法,因此使用旧样式)
    Application.Dialogs(xlDialogCellProtection).Show
End Sub

Sub DeleteShortcut()
    On Error Resume Next
    CommandBars(”MyShortcut”).Delete
End Sub
也可以使用鼠标来显示该快捷菜单,创建一个简单的过程,并通过“宏”对话框中的“选项”按钮分配一个快捷键。
Sub ShowMyShortcutMenu()
‘   Ctrl+Shift+M快捷键
    CommandBars(”MyShortcut”).ShowPopup
End Sub

标签: 没有标签

打开工作簿后只显示用户窗体的方法探讨

问题起源
这是一位网友提出的问题:

  • 如何通过一个窗体录入数据,但是我又不想让人看到整个EXCEL工作薄。简单的说,就是打开某个EXCEL文件之后,我只看到一个窗体,然后我就通过该窗体录入数据,保存之后,所输入的数据就存在EXCEL文件里。

准备示例用户窗体
在VBE编辑器中,插入一个用户窗体,并在其中添加控件,如下图所示:
UserformSample
其相应的代码为:
Private Sub CommandButton1_Click()
    Dim i As Long
    i = Worksheets(”sheet1″).Range(”A65536″).End(xlUp).Row
    If Range(”A1″) = “” Then
        Range(”A1″) = TextBox1.Text
    Else
        i = i + 1
        Range(”A” & i) = TextBox1.Text
    End If
    TextBox1.Text = “”
    TextBox1.SetFocus
End Sub

几种方法探讨
要使代码在工作簿打开时执行,则应利用Workbook_Open事件。一般应该将代码放置在ThisWorkbook模块中,这样在打开该工作簿时会执行其中的代码。
方法1 下面的代码,打开工作簿后,工作表均隐藏,只显示用户窗体,但Excel菜单和工具栏仍显示。
Private Sub Workbook_Open()
    UserForm1.Show
    Workbooks(”Sample1.xls”).Windows(1).Visible = False
End Sub

详见示例Sample1.xls
方法2 下面的代码,在打开工作簿后,将只显示用户窗体。
Private Sub Workbook_Open()
  ‘最小化窗口
  Application.WindowState = xlMinimized
  ‘显示用户窗体
  UserForm1.Show
End Sub

若需在关闭用户窗体后,工作簿也随之前闭,则在用户窗体关闭事件中,添加下面的代码:
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    ThisWorkbook.Close
End Sub

当关闭用户窗体时,Excel会提示用户是否保存对工作簿的修改,单击“是”将保存工作簿并退出。若要默认关闭用户窗体并自动保存工作簿,则添加下面的代码:
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    ThisWorkbook.Close SaveChanges:=True
End Sub

详见示例Sample2.xls
方法3 下面的示例代码,将彻底隐藏工作簿。在打开工作簿后,该工作簿将被隐藏,而只显示用户窗体,即将用户窗体当作用户输入界面,工作簿当作后台数据存储和处理。
Private Sub Workbook_Open()
    ‘隐藏工作簿
    Application.Visible = False
    ‘显示用户窗体
    UserForm1.Show
End Sub

详见示例Sample3.xls
注意:此时,Excel将在后台运行,要退出该Excel应用程序,必须结束其进程。

标签: 没有标签