Excel自动化:保护单个工作表不被用户删除

时间:2010-08-30 02:45:52

标签: c# excel vsto

VSTO 4.0 / Office 2007

在Excel文档级自动化项目中,我有一个不得从工作簿中删除的工作表。我担心粗心的用户可能会意外删除它,这会导致很多悲伤(例外情况)。

我无法保护整个工作簿,因为用户必须能够创建,删除和修改此文件。确切一张需要保护不被删除,但我可能会忽略某些东西,所以如果存在这样的解决方案,我会全神贯注。例如,当工作表可见时,我可以想象我可以Protect()Unprotect()工作簿,但这个解决方案看起来很混乱。

使用以下VBA代码搜索yielded

Private Sub Worksheet_Activate()
Dim CB As CommandBar
Dim Ctrl As CommandBarControl
For Each CB In Application.CommandBars
Set Ctrl = CB.FindControl(ID:=847, recursive:=True)
If Not Ctrl Is Nothing Then
Ctrl.OnAction = "RefuseToDelete"
Ctrl.State = msoButtonUp
End If
Next
End Sub

我不熟悉VBA,但我尝试从VSTO生成的启动方法中运行它:

private void Sheet1_Startup(object sender, System.EventArgs e)
{
    //Is there a neater way to iterate through all Office Collections?
    for (var i = 1; i <= Application.CommandBars.Count; i++)
    {
        var commandBar = Application.CommandBars[i];
        //847 is a magical constant that any fule no has something to do with sheet deletion
        var control = commandBar.FindControl(Id: 847, Recursive: true);
        if (control != null) control.OnAction = null;
    }
}

这段代码似乎什么也没做。您可能会问“嘿,Gleno,您为什么要将OnAction设置为null”,我不知道该将它设置为...链接的VBA解决方案附加到Activate和停用事件,因此有更多代码来自哪里。

提前致谢。

2 个答案:

答案 0 :(得分:2)

今天我必须做一些非常相似的事情。只要您的一个“不可取消”表单处于活动状态,我就会禁用表单删除按钮。如果有一个键盘快捷键来删除工作表,我找不到一个。 (如果有,你也可以禁用它。)

这将出现在你的ThisWorkbook课程中:

    private void ThisWorkbook_Startup(object sender, System.EventArgs e)
    {
        this.SheetActivate += (sh) =>
            {
                this.ribbon.InvalidateBuiltinControl("SheetDelete");
            };
    }

    public bool CanDeleteActiveSheet()
    {
        if (this.ActiveSheet == null)
            return true;

        // Replace Sheet1 with your sheet's CodeName
        return ((Excel.Worksheet)this.ActiveSheet).CodeName != "Sheet1";
    }

    // Keep a local reference to the ribbon in your ThisWorkbook class
    // so you can call InvalidateControl() from it.
    Ribbon ribbon;
    protected override IRibbonExtensibility CreateRibbonExtensibilityObject()
    {
        this.ribbon = new Ribbon();
        return this.ribbon;
    }

这将在您的功能区代码后面:

    public void InvalidateBuiltinControl(string controlID)
    {
        this.ribbon.InvalidateControlMso(controlID);
    }

    public bool deleteButton_GetEnabled(IRibbonControl control)
    {
        return Globals.ThisWorkbook.CanDeleteActiveSheet();
    }

这将在你的功能区xml:

<commands>
    <command idMso="SheetDelete" getEnabled="deleteButton_GetEnabled" />
</commands>

我仍然对在ThisWorkbook中保留那个功能区参考有点怀疑,但到目前为止还没有人在the question I posted earlier中提到更好的方法。希望这有帮助!

答案 1 :(得分:1)

我遇到类似的问题,我知道如何保护工作表,但是我需要在使用SQL连接填充外部数据后打开保护。我找不到正确的事件来做这件事。

这可以帮助您将其放入工作表的启动事件中:

Me.Protect(密码:=“密码”,allowFiltering:= True,allowSorting:= True,allowUsingPivotTables:= True)