質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

1回答

12113閲覧

C# 遅延バインディングでExcel操作_InvokeMember関数の引数の調べ方

yoshin

総合スコア39

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

1クリップ

投稿2016/11/16 01:54

###前提・実現したいこと
C#にてWindowsFormアプリケーションを作成しています。
アプリケーション内でExcelを扱うのですが、Excelのバージョン違いを吸収する必要があります。
調べたところ、遅延バインディングでExcelを操作すれば良いことがわかりました。

また、ソースコードに記述したように、

・オブジェクトの型をGetType()で取得
・取得した方が保有するメンバー(メソッド・プロパティ)にInvokeMember()関数を使ってアクセス

以上でWorkbookやworksheetに対する操作ができることがわかりました。

###教えていただきたいこと

InvokeMember()関数は引数に、
・呼び出すメソッドやプロパティ名
・呼び出すメンバーに渡される引数を格納する配列
等が必要になるのですが、それらをどうやって調べればよいか教えてください。
https://msdn.microsoft.com/ja-jp/library/66btctbe(v=vs.110).aspx

たとえばWorkbookを操作したいとき、
Workbookがどんなメソッドやプロパティを保有しているのか、
またそれらを呼び出すときにどんな引数をわたせば良いのか、
といったことが知りたいです。
(WorksheetやCellも同様の内容が知りたい)

###該当のソースコード

// Excelアプリケーションオブジェクト生成 Type objClassType = Type.GetTypeFromProgID("Excel.Application"); objApp = Activator.CreateInstance(objClassType); // workbooksオブジェクト取得 object objBooks = objApp.GetType().InvokeMember( "Workbooks", BindingFlags.GetProperty, null, objApp, null ); // workbook追加 object objBook = objBooks.GetType().InvokeMember( "Add", BindingFlags.InvokeMethod, null, objBooks, null ); // worksheetsオブジェクト取得 object objSheets = objBook.GetType().InvokeMember( "Worksheets", BindingFlags.GetProperty, null, objBook, null );

###補足情報(言語/FW/ツール等のバージョンなど)
.NET Framework4
Visual Studio 2015

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

型(クラス、構造体など)のすべてのメンバを取得する
COMオブジェクトはちょっと試したことないのでわかりませんが、普通のクラスはこれでなんとかできます。

ただ、エクセルの関数は引数大量にあって、まともに取り合うのはめちゃくちゃ面倒です。(実際は引数の大半はデフォルト値で十分だったり)

個人的には素直にこういうところを参考にして足りないものがあったらリファレンスや参考サイト見ながら一つ一つ機能を足していくほうがいいと思います。

投稿2016/11/16 02:05

編集2016/11/16 02:10
ishi9

総合スコア1294

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yoshin

2016/11/16 03:17

こんにちは。 回答いただきありがとうございます。 >>型(クラス、構造体など)のすべてのメンバを取得する ⇒COMオブジェクトで試してみますね。 >>こういうところを参考にして ⇒とても参考になりそうなサイトでした。  教えていただきありがとうございます。
yoshin

2016/11/16 04:16

>>型(クラス、構造体など)のすべてのメンバを取得する ⇒試してみましたが、期待した結果が得られませんでした。   以下のコードでobjBookに対してメンバーを取得しようとしましたが、    // workbook追加  object objBook = objBooks.GetType().InvokeMember( "Add", BindingFlags.InvokeMethod, null, objBooks, null );  Type bookType = objBook .GetType(); System.Reflection.MemberInfo[] members = bookType.GetMembers(); bookTypeのName は _ComObject として取得され、 membersも_ComObject の メンバーが取得されるという形になりました。
yoshin

2016/11/16 04:22

>>足りないものがあったらリファレンスや参考サイト見ながら ただ、よくよく考えてみると私が知りことは回答者さんがおっしゃるとおり Excelを操作するときのリファレンスを調べればよいはずです。 そもそもどのリファレンスを見ればよいのかわからなかったのですが、 https://msdn.microsoft.com/ja-jp/library/microsoft.office.interop.excel(v=office.11).aspx を参照すればよいのかなぁと思いました。 違ってたらご指摘ください。
ishi9

2016/11/16 04:48 編集

>>試してみましたが、期待した結果が得られませんでした。 すいません、やっぱりCOMオブジェクトだと勝手が違いましたね。 こちらの方は引き続き情報必要でしょうか?(一個一個追加するなら必要はなさそうですが) >>そもそもどのリファレンスを見ればよいのかわからなかったのですが、 はい、そこで合っています。似ててややこしいですが、Microsoft.Office.Tools.Excelというのもあるので(中の関数や機能も似ている)注意してください。ToolsはExcelのアドイン用です(確か) リファレンスだけだと引数が大量にあるやつとか、まるで使い方がわからなかったりするので、 そういうときは(実質的な)使い方を紹介しているサイトとかを参考にした方が早いです。
yoshin

2016/11/16 07:09

>>こちらの方は引き続き情報必要でしょうか?(一個一個追加するなら必要はなさそうですが) ありがとうございます。一個一個追加するので必要なくなりました。 追加で困ったことが発生してしまいました。 遅延バインディングで指定した範囲のセルを取得し、 読み込み、および書込み処理を高速化したいと思っています。 調べたところ2次元配列にセルの値をセットすれば良いみたいなのですが、 遅延バインディングでの方法がわかりません。 http://wannabe-note.com/1160 ご存知でしたら教えていただけないでしょうか? (参考になるサイトでも結構です。) 本来の質問からずれしまっているので必要であれば別にスレッドを立てます。 いろいろお聞きしてしまい、申し訳ありません。
ishi9

2016/11/16 07:33

私が最初に提示した参考サイトにGetRangeという関数があります。これで取得できたRangeオブジェクトにはValue2というプロパティがあるのでこれにobject[,]を設定します(SetCellTextでやっているのと同じです) それ以外の流れは同サイトにあるGetCellValueとSetCellValueと大体同じ流れです。
yoshin

2016/11/16 08:55

教えていただいたサイトのメソッドを使って配列にセルの値をセットすることができました。 いろいろと親切に教えていただき本当にありがとうございました。 助かりました。 コードはかなり省略しますが、以下のような感じになりました。 //Getrangeメソッドでセル範囲を取得 object targetRange = excelApp.GetRange(sheet, cell1, cell2); //二次元配列に値をセット object[,] obj1 = (System.Object[,])targetRange.GetType().InvokeMember("Value2", BindingFlags.GetProperty, null, targetRange, null); ※一部変更:GetRangeメソッドに第3引数を追加しました。 public object GetRange(object sheet, object cell1,object cell2) //同様に書込み先の範囲を取得してからValue2に配列の値をセット object[] parameters = new Object[1]; parameters[0] = obj1; writeRange.GetType().InvokeMember("Value2", BindingFlags.SetProperty, null, writeRange, parameters);
ishi9

2016/11/16 09:06

無事に出来て良かったです。 文字列から直接cellを渡す方法に変えたのですね。確かにそっちの方が使い勝手がよさそうです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問