2011-01-02 17 views
2

Ich versuche, automatische Variablen für Excel VBA verfügbar zu machen (wie ActiveSheet oder ActiveCell), die PowerShell auch als 'automatische Variablen' zur Verfügung stehen. Die PowerShell-Engine wird in einem Excel VSTO-Add-In und in Excel gehostet. Die Anwendung steht ihr als Globals.ThisAddin.Application zur Verfügung. Ich fand this Thread hier auf Stackoverflow und begann PSVariable abgeleiteten Klassen erstellt wie:Automatische PowerShell-Variablen von C# erstellen

public class ActiveCell : PSVariable 
{ 
    public ActiveCell(string name) : base(name) { } 

    public override object Value 
    { 
     get 
     { 
      return Globals.ThisAddIn.Application.ActiveCell; 
     } 
    } 
} 

public class ActiveSheet : PSVariable 
{ 
    public ActiveSheet(string name) : base(name) { } 

    public override object Value 
    { 
     get 
     { 
      return Globals.ThisAddIn.Application.ActiveSheet; 
     } 
    } 
} 

und das Hinzufügen von den Instanzen der aktuellen Powershell-Sitzung:

runspace.SessionStateProxy.PSVariable.Set(new ActiveCell("ActiveCell")); 
runspace.SessionStateProxy.PSVariable.Set(new ActiveSheet("ActiveSheet")); 

Dies funktioniert und ich bin in der Lage, diese Variablen zu verwenden, um von PowerShell als $ ActiveCell und $ ActiveSheet (ihr Wert ändert sich als Excel-Blatt oder -Zelle). Dann las ich PSVariable Dokumentation here und sah dies:

"Es gibt kein etabliertes Szenario zum Ableiten von dieser Klasse. Um eine Shell-Variable programmgesteuert zu erstellen, erstellen Sie eine Instanz dieser Klasse und legen Sie sie mithilfe der PSVariableIntrinsics-Klasse."

Wie ich aus PSVariable wurde abgeleitet, habe ich versucht, zu verwenden, was vorgeschlagen wurde:

PSVariable activeCell = new PSVariable("ActiveCell"); 
activeCell.Value = Globals.ThisAddIn.Application.ActiveCell; 
runspace.SessionStateProxy.PSVariable.Set(activeCell); 

Mit diesem $ Active in meiner Powershell-Sitzung erscheint, aber sein Wert ändert sich nicht, wie ich die aktive Zelle ändern in Excel.

Ist der obige Kommentar aus der PSVariable-Dokumentation etwas, worüber ich mich Sorgen machen sollte, oder kann ich weiterhin PSVariable-abgeleitete Klassen erstellen? Gibt es eine andere Möglichkeit, Excel-Globals für PowerShell verfügbar zu machen?

Antwort

0

Offensichtlich können Sie in Ihrem zweiten Beispiel, wo Sie nicht von PSVariable ableiten, nicht erwarten, dass sich die $ ActiveCell-Variable mit dem Wert der ActiveCell-Eigenschaft ändert, da Sie ihren Wert nur einmal erfassen.

Ich glaube nicht, abgeleitet von PSVariable ist ein unterstütztes Szenario, aber es funktioniert und ich habe es getan, um Variablen wie $Now und $Today hinzuzufügen.

Es könnte eine bessere Idee sein, einfach eine $ Application-Variable dem PowerShell-Skript und nicht den verschiedenen Eigenschaften des Application-Objekts zur Verfügung zu stellen. Der Vorteil besteht darin, dass Sie nicht eine Reihe von automatischen Variablen erstellen müssen und PowerShell-Skripts mit dem Programm $ Application.ActiveCell auf alles zugreifen können, was das Application-Objekt zu bieten hat. Der andere Vorteil besteht darin, dass es keine automatische Variable sein muss, da sich die Referenz des Anwendungsobjekts niemals ändert.

Nachdem ich all das gesagt habe, habe ich eine Unterklasse von PSVariable eingefügt, die ich von Zeit zu Zeit benutze, die einen ScriptBlock für den Getter und Setter benötigt. Dadurch kann ich automatische Variablen aus PowerShell definieren, ohne dass für jede eine separate abgeleitete Klasse benötigt wird.

using System; 
using System.Management.Automation; 

namespace Einstein.PowerShell 
{ 

    public sealed class DynamicVariable : PSVariable 
    { 

     #region Constructors 

     /// <summary> 
     /// </summary> 
     public DynamicVariable(string name, ScriptBlock onGet) 
      : this(name, onGet, null) 
     { 
     } 

     /// <summary> 
     /// </summary> 
     public DynamicVariable(string name, ScriptBlock onGet, ScriptBlock onSet) 
      : base(name, null, ScopedItemOptions.AllScope) 
     { 
      OnGet = onGet; 
      OnSet = onSet; 
     } 

     #endregion 

     #region Properties 

     /// <summary> 
     /// The ScriptBlock that runs to get the value of the variable. 
     /// </summary> 
     private ScriptBlock OnGet 
     { 
      get; 
      set; 
     } 

     /// <summary> 
     /// The ScriptBlock that runs to get the value of the variable. 
     /// </summary> 
     private ScriptBlock OnSet 
     { 
      get; 
      set; 
     } 

     /// <summary> 
     /// Gets or sets the underlying value of the variable. 
     /// </summary> 
     public override object Value 
     { 
      get 
      { 
       if (OnGet == null) { 
        return null; 
       } 
       return OnGet.Invoke(); 
      } 
      set 
      { 
       if (OnSet == null) { 
        throw new InvalidOperationException("The variable is read-only."); 
       } 
       OnSet.Invoke(value); 
      } 
     } 

     #endregion 

    } 

} 
+0

ich bereits Excel aus. Anwendung als $ -Anwendung, Ich benutze Runspace.SessionStateProxy.SetVariable ("Application", App) und es funktioniert gut (App ist eine Microsoft.Office.Interop.Exce.Application-Instanz). Ich weiß, dass ich Application.ActiveCell oder Application.ActiveSheet verwenden kann, aber ich habe versucht, eine Umgebung ähnlich Excel VBA zu erstellen, in der ActiveCell und ActiveSheet als Globals verfügbar sind. Vielen Dank. –

Verwandte Themen