0

保護されたシートでは、Excel テーブル (ListObjects) の並べ替えは許可されていません。次のエラー メッセージが表示されます。

ここに画像の説明を入力

私は解決策を探すのに何週間も費やしましたが、成功しませんでした。そこにあるものはすべて、Excel 2007 のコード サンプルでは古くなっています。この制限を回避する方法に関するチュートリアルやガイドはありません。

最終的に克服できた方法はこちら..

4

1 に答える 1

0

テーブルの Excel のフィルタ ドロップダウン メニューからソートする場合、トラップ可能なイベントはありません。ただし、昇順、降順、または並べ替えのダイアログ コマンドがリボンの [ホーム] タブおよび [データ] タブから呼び出されたときに、イベントをトラップすることはできます。

Excel 2016 相互運用機能 (ドキュメント レベルのカスタマイズ)、Visual Studio 2015、および C# を使用:


  1. プロジェクトを右クリック -> 追加 -> 新しいアイテム -> リボン (XML)

  2. あなたの Ribbon.xml で:

<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
  <commands>  
    <command idMso="SortAscendingExcel" onAction="SortNoAlerts" />
    <command idMso="SortDescendingExcel" onAction="SortNoAlerts" />
    <command idMso="SortCustomExcel" onAction="SortDialogNoAlerts" /><!--TabHome-->
    <command idMso="SortDialog" onAction="SortDialogNoAlerts" /><!--TabData-->
  </commands>
</customUI>

次に、イベントのコールバック関数を追加します。SortNoAlerts昇順/降順ボタンのクリックに対してシートの保護を解除します。ただし、ユーザーが [カスタム ソート] ([ホーム] タブ) または [並べ替え] ([データ] タブ) を選択すると、ダイアログが表示され、シートの保護が解除され、[OK] を押すとシートが保護されますが、ユーザーがキャンセルした場合、ThisWorkbook_SheetCalculateシートを保護しないままにすることは決してありません。SortDialogNoAlertsそのため、シートの保護を解除するだけでなく、p/Invoke を使用FindWindowして並べ替えダイアログ ウィンドウを探すタイマーを開始するを追加します。ウィンドウが見つからなくなると、まだ保護されていなければ保護されます。

  1. Ribbon.cs コールバックで:
    public void SortNoAlerts(Office.IRibbonControl control, ref bool cancelDefault)
    {
        Excel.Worksheet ws = null;
        try
        {
            ws = (Excel.Worksheet)Globals.ThisWorkbook.ActiveSheet;
            ws.Unprotect("your password");
            cancelDefault = false;
        }
        catch (Exception) { }
        finally
        {
            if (ws != null) Marshal.ReleaseComObject(ws); ws = null;
        }
    }

    public void SortDialogNoAlerts(Office.IRibbonControl control, ref bool cancelDefault)
    {
        Excel.Worksheet ws = null;
        try
        {
            ws = (Excel.Worksheet)Globals.ThisWorkbook.ActiveSheet;
            ws.Unprotect("your password");
            Globals.ThisWorkbook._myActionPane.tmrWaitSortWinClose.Enabled = true;
            cancelDefault = false;
        }
        catch (Exception) {
            Globals.ThisWorkbook._myActionPane.tmrWaitSortWinClose.Enabled = false;
        }
        finally
        {
            if (ws != null) Marshal.ReleaseComObject(ws); ws = null;
        }
    }
  1. ThisWorkbook.cs -> InternalStartup() にこれを追加します。
this.SheetCalculate += new Excel.WorkbookEvents_SheetCalculateEventHandler(ThisWorkbook_SheetCalculate);
  1. ThisWorkbook.cs で -> これを追加します。
public bool sortDialogVisible;

private void ThisWorkbook_SheetCalculate(object sh)
{
  Excel.Worksheet ws = (Excel.Worksheet)sh;
  ws.EnableOutlining = true;
  ws.Protect("your password", true, Type.Missing, Type.Missing, true, true, true, Type.Missing, Type.Missing, true, Type.Missing, Type.Missing, true, true, true, Type.Missing);
  Marshal.ReleaseComObject(ws); ws = null;
}
  1. tmrWaitSortWinClose という名前のタイマーを追加し、Interval = 750 に設定します。
private void tmrWaitSortWinClose_Tick(object sender, EventArgs e)
{
    Globals.ThisWorkbook.sortDialogVisible = Native.FindWindow("NUIDialog", "Sort") == IntPtr.Zero;

    if (Globals.ThisWorkbook.sortDialogVisible)
    {
        Excel.Worksheet ws = null;
        try
        {
            ws = (Excel.Worksheet)Globals.ThisWorkbook.ActiveSheet;

            if (!ws.ProtectContents)
            {
               ws.Protect("your password", true, Type.Missing, Type.Missing, true, true, true, Type.Missing, Type.Missing, true, Type.Missing, Type.Missing, true, true, true, Type.Missing);
            }
            tmrWaitSortWinClose.Enabled = false;
        }
        catch (Exception) { tmrWaitSortWinClose.Enabled = false; }
        finally
        {
            if (ws != null) Marshal.ReleaseComObject(ws); ws = null;
        }
    }
}
  1. Native.cs という名前のクラスを追加します。
public class Native
{
    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
}

これにより、保護されたシートでテーブルを並べ替えることができます。混乱しないでください。このAllowSortオプションはworksheet.Protect()、テーブル (ListObject) の一部ではないシートのセルのみを対象としています。

于 2016-11-02T01:36:16.880 に答える