Автоматизация Excel: защита одного листа от удаления пользователем - PullRequest
1 голос
/ 30 августа 2010

VSTO 4.0 / Office 2007

В проекте автоматизации уровня документа Excel у меня есть рабочий лист, который нельзя удалять из рабочей книги . Я боюсь, что неосторожный пользователь может удалить его случайно, что в настоящее время вызывает много горя (исключений в изобилии).

Я не могу защитить всю книгу, потому что пользователь должен иметь возможность создавать, удалять и иным образом изменять этот файл. Точно один лист должен быть защищен от удаления, но я могу что-то пропустить, поэтому, если такое решение существует, я весь слух. Например, я мог представить, что могу Protect() и Unprotect() книгу, когда лист виден, но это решение кажется грязным.

Googling дал следующий код 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 ]

2 голосов
/ 06 января 2011

Я должен был сделать что-то очень похожее сегодня. Я бы просто отключил кнопки удаления листа, когда активен твой один «не удаляемый» лист. Если для удаления листа есть сочетание клавиш, я не могу его найти. (Если есть, вы можете отключить это тоже.)

Это будет в вашем классе 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, но пока никто не упомянул лучший способ в вопросе, который я разместил ранее . Надеюсь, это поможет!

1 голос
/ 05 января 2011

У меня похожая проблема, когда я знаю, как защитить лист, но мне нужно включить защиту после заполнения листа внешними данными из соединения SQL.Я не могу найти правильное событие для этого.

Это должно помочь вам поместить его в событие запуска для рабочего листа:

Me.Protect (password: = "password", allowFiltering: =True, allowSorting: = True, allowUsingPivotTables: = True)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...