2016-11-02 6 views
0

Das Sortieren von Excel-Tabellen (ListObjects) ist auf geschützten Blättern nicht erlaubt. Sie werden die folgende Fehlermeldung angezeigt:Excel-Tabelle (ListObject) auf geschütztem Blatt mit Excel-Interop sortieren

enter image description here

ich Wochen lang ohne Erfolg nach einer Lösung suchen. Alles, was es da draußen gibt, ist mit Excel 2007-Codebeispielen veraltet. Es gibt keine Anleitungen oder Anleitungen, wie diese Einschränkung umgangen werden kann.

Hier ist, wie ich in der Lage war zu überwinden, um endlich ..

Antwort

0

Es gibt kein auffangbar Ereignis ist, wenn aus dem Excel-Filter Dropdown-Menü aus einer Tabelle zu sortieren. Sie können die Ereignisse jedoch abfangen, wenn auf den Registerkarten "Start" und "Daten" der Multifunktionsleiste Befehle für aufsteigende, absteigende oder Sortierdialoge aufgerufen werden.

Mit Excel 2016 Interop (Anpassung auf Dokumentebene), Visual Studio 2015 und C#:


  1. Rechtsklick auf das Projekt -> Add -> Neue Artikel -> Band (XML)

  2. Auf Ihrem 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> 

Als nächstes fügen Sie die Rückruffunktionen der Ereignisse hinzu. SortNoAlerts deaktiviert das Blatt für aufsteigende/absteigende Schaltflächenklicks. Wenn der Benutzer jedoch 'Benutzerdefiniert' (Registerkarte Start) - oder - 'Sort' (Registerkarte Daten) auswählt, wird ein Dialogfeld angezeigt, das den Schutz des Blattes aufhebt und es schützt, wenn OK gedrückt wird Wenn der Benutzer Bricht, ThisWorkbook_SheetCalculate löst nie aus, dass das Blatt ungeschützt bleibt. Also fügen wir die SortDialogNoAlerts hinzu, die das Blatt entschützt, aber startet auch einen Timer, der p/Invoke FindWindow verwendet, um nach dem Dialogfenster Sortieren zu suchen. Wenn das Fenster nicht mehr gefunden wird, schützt es es, wenn es nicht bereits geschützt ist.

  1. Auf Ihrem Ribbon.cs Rückruf:
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. Auf ThisWorkbook.cs -> InternalStartup() fügen Sie diese:
this.SheetCalculate += new Excel.WorkbookEvents_SheetCalculateEventHandler(ThisWorkbook_SheetCalculate); 
  1. Auf ThisWorkbook.cs -> Fügen Sie diese:
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. einen Timer hinzufügen namens tmrWaitSortWinClose und setzen Intervall = 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. Fügen Sie eine Klasse namens Native.cs hinzu:
public class Native 
{ 
    [DllImport("user32.dll", SetLastError = true)] 
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); 
} 

, die Tabellen auf geschützte Sortieren von Blättern ermöglichen. Seien Sie nicht verwirrt, die AllowSort Option von worksheet.Protect() es ist nur für die Zellen des Blattes, die nicht Teil einer Tabelle sind (ListObject).

Verwandte Themen