代码之家  ›  专栏  ›  技术社区  ›  Gleno

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

  •  1
  • Gleno  · 技术社区  · 14 年前

    VSTO 4.0/办公室2007

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

    我无法保护整个工作簿,因为用户必须能够创建、删除或修改此文件。确切地 一张纸 需要防止删除,但我可能忽略了一些东西,所以如果存在这样的解决方案,我会全力以赴。例如,我可以想象我可以 Protect() Unprotect() 工作表可见时的工作簿,但此解决方案似乎混乱。

    网上搜索 yielded 以下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;
        }
    }
    

    这段代码似乎什么都不做。你可能会问 “嘿,格伦诺,你为什么这么做? OnAction “零” 我不知道该怎么设置…链接的VBA解决方案附加到激活和停用事件,因此有更多的代码从何而来。

    事先谢谢。

    2 回复  |  直到 14 年前
        1
  •  2
  •   Community CDub    8 年前

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

    这将出现在您的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>
    

    我还是有点不敢相信这份工作手册中提到的丝带,但是到目前为止还没有人提到更好的方法。 the question I posted earlier . 希望这有帮助!

        2
  •  1
  •   Rod    14 年前

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

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

    me.protect(password:=“密码”,allowfiltering:=true,allowsorting:=true,allowusingPivotTables:=true)