C# Excel自动化:防止单个工作表被用户删除

C# Excel自动化:防止单个工作表被用户删除,c#,excel,vsto,C#,Excel,Vsto,VSTO 4.0/Office 2007 在Excel文档级自动化项目中,我有一个工作表,不能从工作簿中删除。我担心粗心的用户可能会意外地删除它,这目前会造成很多悲伤(大量例外) 我无法保护整个工作簿,因为用户必须能够创建、删除或以其他方式修改此文件。正好有一张纸需要保护以免被删除,但我可能忽略了一些东西,所以如果有这样的解决方案,我会洗耳恭听。例如,我可以想象,当工作表可见时,我可以Protect()和Unprotect()工作簿,但是这个解决方案看起来很混乱 用谷歌搜索以下VBA代码: Pr

VSTO 4.0/Office 2007

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

我无法保护整个工作簿,因为用户必须能够创建、删除或以其他方式修改此文件。正好有一张纸需要保护以免被删除,但我可能忽略了一些东西,所以如果有这样的解决方案,我会洗耳恭听。例如,我可以想象,当工作表可见时,我可以
Protect()
Unprotect()
工作簿,但是这个解决方案看起来很混乱

用谷歌搜索以下VBA代码:

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;
    }
}
private void Sheet1\u启动(对象发送方,System.EventArgs e)
{
//是否有一种更整洁的方法来遍历所有Office集合?

对于(var i=1;i我遇到了一个类似的问题,我知道如何保护工作表,但在使用来自SQL连接的外部数据填充工作表后,我需要打开保护。我找不到正确的事件来执行此操作

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


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

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

这将出现在您的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();
    }
这将包含在ribbon xml中:

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


我仍然有点不愿意在这本手册中保留ribbon参考资料,但到目前为止还没有人提到更好的方法。希望这会有帮助!

谢谢Nick。如果我不得不再次使用office对象模型,那就太快了。:)哈哈哈。我会告诉你,现在比几年前更好了!