Excelの参照設定を行わず、遅延バインディングを回避するには?

解決


ドン吉  2009-07-14 20:55:35  No: 146070

以下の条件でVB.NET内でExcelを操作したいと思っております。

■条件■
1.参照設定(Microsoft Excel XX.X Object Library)を設定しない
2.Option Strict Off には設定しない。

■やりたいこと■

クラス内にて、以下のように記述しております。

Public Function SetRange(strCell as String) as object

   objxlsApp = CreateObject("Excel.Application")
   objxlsWorkBooks = objxlsApp.Workbooks
   objxlsSheets = objxlsWorkBook.Worksheets
   objxlsSheet = objxlsSheets("Sheet1")

   objxlsRange = objxlsSheet.Range(strCell )

   Return objxlsRange
End Function

上記の関数を

クラス名.SetRange("A1").Value = "テスト"

というように使用したいのですが、 「遅延バインディングを使用できません」と表示されます。
■条件■を満たしながらの回避方法をご存じであれば、ご教授ください。

※参照設定を行った場合は、Public Function SetRange(strCell as String) as Excel.Range
  と記述できるので問題はありませんでした。


魔界の仮面弁士  2009-07-14 21:04:25  No: 146071

CallByName を利用してみてください。


ドン吉  2009-07-14 22:39:33  No: 146072

回答ありがとうございます。

クラス名.SetRange("A1").Value = "テスト"

というように使用したいのも前提です。

objextの引き渡し方に何か対策がないでしょうか?


魔界の仮面弁士  2009-07-14 23:08:06  No: 146073

> クラス名.SetRange("A1").Value = "テスト"
> というように使用したいのも前提です。

Option Strict はファイル単位に設定できますが、
一部のみ On/Off を切り替える訳にはいかないのでしょうか?

それが駄目なら、やはり CallByName (またはリフレクション)が必要かと。
  CallByName(クラス名.SetRange("A1"), "Value", vbLet, "テスト")

もし On のまま、かつ、CallByName やリフレクション無しでという条件なら、
  クラス名.SetRange("A1").Value = "テスト"
の SetRange メソッドの戻り値を、「Value プロパティを持った自作クラス」に
差し替えて対応するか、もしくはSetRange メソッドの代わりに、
  クラス名.SetValue("A1", "テスト")
の構文に改造する必要があるかと思います。
(相手が Object 型でなければ、拡張メソッドという手が使えますが…)


ドン吉  2009-07-14 23:23:18  No: 146074

説明が不十分で申し訳ございません。

クラス名.SetRange("A1").Value = "テスト"
と使用したいのは一部です。

クラス名.SetRange("A1").XXXX = ○○○○○○

といった具合に、"A1"をRange化したものを扱いたいと思っております。

objectという受け渡しの形にはこだわっておりませんので、
>(相手が Object 型でなければ、拡張メソッドという手が使えますが…)
上記の例をご教授願えませんでしょうか?


魔界の仮面弁士  2009-07-15 02:37:37  No: 146075

> クラス名.SetRange("A1").Value = "テスト"

まず、Excel.Range オブジェクトの解放処理(Marshal.ReleaseComObject)を
どのタイミングで行う予定でしょうか?

通常通り、利用側に処理させる仕様にするのであれば、
  x = クラス名.SetRange("A1")
  x.Value = "テスト"
  Marshal.ReleaseComObject(x)
となるでしょう(あるいは、IDisposable にして Using させるか…)。

一方、解放の責務を(利用側では無く)クラス側に負わせるなら、先の回答のように

(案1)
  クラス名.SetValue("A1", "テスト") の構文にして、
  解放処理をこのメソッド内に収める。

(案2)
  クラス名.SetRange("A1").Value = "テスト" の構文で SetRange が返すオブジェクトを、
  Excel の Range クラスではなく、COM オブジェクトを含まないマネージクラスにする。
  (そしてこれが先の、「Value プロパティを持った自作クラス」の話に繋がってきます。)

などが考えられます。案2の実装は大変そうですけれども。
(他にも手はあるでしょうが、どの方法が良いのかはケースバイケースかと)

> と使用したいのは一部です。
もちろん、Value 以外のメンバも実装しなければなりませんね。
その場合、どの範囲までを対象としますか?

単に Excel の Range オブジェクトを扱うだけでも、200 以上のメンバ定義が
ありますし、Excel のバージョンによっても定義に差があるのが現状です。

結果、参照設定無しで運用する場合、
  (a) 一部のメンバーのみをカプセル化する。
  (b) すべてのメンバーをカプセル化する。
  (c) レイトバインドで運用する。
の選択が必要になってきます。b 案は理想ですが、現実的では無いでしょうね。

>> (相手が Object 型でなければ、拡張メソッドという手が使えますが…)
> 上記の例をご教授願えませんでしょうか?
下記の拡張メソッドの解説記事を参照してみてください。
http://msdn.microsoft.com/ja-jp/magazine/cc163317.aspx


ドン吉  2009-07-22 23:51:26  No: 146076

こちらの件、案2で解決させていただきました。
大変参考になり、助かりました。

本当にありがとうございました。

(案2)
  クラス名.SetRange("A1").Value = "テスト" の構文で SetRange が返すオブジェクトを、
  Excel の Range クラスではなく、COM オブジェクトを含まないマネージクラスにする。
  (そしてこれが先の、「Value プロパティを持った自作クラス」の話に繋がってきます。)


※返信する前に利用規約をご確認ください。




  


  このエントリーをはてなブックマークに追加