3

自動変数を Excel VBA (ActiveSheet や ActiveCell など) で利用できるようにしようとしていますが、PowerShell でも「自動変数」として利用できます。PowerShell エンジンは Excel VSTO アドインでホストされ、Excel.Application は Globals.ThisAddin.Application として利用できます。StackOverflow でこのスレッドを見つけ、次のような PSVariable 派生クラスの作成を開始しました。

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; 
        }
    }
}

インスタンスを現在の POWERShell セッションに追加します。

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

これは機能し、PowerShell のこれらの変数を $ActiveCell および $ActiveSheet として使用できます (それらの値は、Excel のアクティブ シートまたはセルの変更として変化します)。次に、ここでPSVariable のドキュメントを読んで、これを見ました。

「このクラスから派生するための確立されたシナリオはありません。プログラムでシェル変数を作成するには、このクラスのインスタンスを作成し、PSVariableIntrinsics クラスを使用して設定します。」

私は PSVariable から派生していたので、提案されたものを使用しようとしました:

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

これを使用すると、PowerShell セッションに $ActiveCell が表示されますが、Excel でアクティブ セルを変更しても値は変わりません。

PSVariable ドキュメントからの上記のコメントは、私が心配する必要があるものですか、それとも PSVariable 派生クラスの作成を続行できますか? Excel グローバルを PowerShell で使用できるようにする別の方法はありますか?

4

2 に答える 2

5

私たちのドキュメントは間違っています - これはサポートされているシナリオです。

このテクニックについてもう少し詳しく説明します。

  1. http://poshcode.org/2198
  2. http://www.leeholmes.com/blog/2009/03/26/more-tied-variables-in-powershell/
  3. http://www.pavleck.net/powershell-cookbook/ch03.html

Lee Holmes [MSFT] Windows PowerShell 開発

于 2011-01-02T22:49:53.943 に答える
0

明らかに、PSVariable から派生していない 2 番目の例では、値を一度だけキャプチャしているため、 $ActiveCell 変数が ActiveCell プロパティの値で変化するとは期待できませんでした。

PSVariable からの派生はサポートされているシナリオではないと思いますが、それは機能し、 や などの変数を追加するために実行しまし$Now$Today

Application オブジェクトのさまざまなプロパティではなく、$Application 変数を PowerShell スクリプトに公開することをお勧めします。これの利点は、一連の自動変数を作成する必要がなく、PowerShell スクリプトが $Application.ActiveCell を使用して Application オブジェクトが提供するすべてのものにアクセスできることです。もう 1 つの利点は、Application オブジェクトの参照が変更されないため、自動変数である必要がまったくないことです。

そうは言っても、時々使用する PSVariable のサブクラスを含めました。これはゲッターとセッターに ScriptBlock を使用します。これにより、PowerShell から自動変数を定義できるようになり、それぞれの派生クラスを個別に作成する必要がなくなりました。

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

    }

}
于 2011-01-02T22:09:55.700 に答える