DOBON.NET DOBON.NETプログラミング掲示板過去ログ

Excel上からプログラムを実行したときのアクティブセル情報

環境/言語:[C#]
分類:[.NET]

はじめまして。

Excel上からプログラムを呼び出して実行したいのですが、
このとき開いているExcelのアクティブなセルのアドレスを得られません。

一度
http://oshiete1.goo.ne.jp/qa4597523.html
で質問して出来たと思ったのですが、最初に開いているExcelのアクティブなセルを得られていませんでした。

どうすれば良いのでしょうか?

string t;
Excel.Application oApplication = null;
Excel.Range oRange = null;

oApplication = new Excel.Application();
Excel.Workbook oWBook;
oWBook = (Excel.Workbook)(oApplication.Workbooks.Open(
@"C:Bookwork.xlsm", // オープンするExcelファイル名
Type.Missing, // (省略可能)UpdateLinks (0 / 1 / 2 / 3)
Type.Missing, // (省略可能)ReadOnly (True / False )
Type.Missing, // (省略可能)Format
// 1:タブ / 2:カンマ (,) / 3:スペース / 4:セミコロン (;)
// 5:なし / 6:引数 Delimiterで指定された文字
Type.Missing, // (省略可能)Password
Type.Missing, // (省略可能)WriteResPassword
Type.Missing, // (省略可能)IgnoreReadOnlyRecommended
Type.Missing, // (省略可能)Origin
Type.Missing, // (省略可能)Delimiter
Type.Missing, // (省略可能)Editable
Type.Missing, // (省略可能)Notify
Type.Missing, // (省略可能)Converter
Type.Missing, // (省略可能)AddToMru
Type.Missing, // (省略可能)Local
Type.Missing // (省略可能)CorruptLoad
));
oRange = oApplication.ActiveCell;

t = oRange.get_Address(Type.Missing, Type.Missing, Excel.XlReferenceStyle.xlA1, Type.Missing, Type.Missing);
MessageBox.Show(t);

よろしくお願いいたします。
2009/01/08(Thu) 11:15:15 編集(投稿者)

■No23742に返信(andAさんの記事)
> このとき開いているExcelのアクティブなセルのアドレスを得られません。
こういう場合には、具体的な状況を記述した方が回答を得やすいですよ。

☆oApplication.ActiveCell がエラーになるのか?
  → 具体的なエラー内容を記述してください。

☆oApplication.ActiveCell が null を返すのか?
  → そもそも、アクティブなセルがあるかどうかを確認してみてください。
   たとえば(ワークシートではなく)グラフシートがアクティブになっている場合、
   Application.ActiveCell は Nothing (C# では null)を返します。
  → ワークシートがアクティブであるはずなのに、null を返すのであれば、
   Visible = True にて Excel を表示させてから、再度チャレンジしてみてください。
  → それでも駄目な場合は、一度 Window オブジェクトを経由させて、
   そこから ActiveCell を得る事ができないかどうか、確認してみてください。

☆oRange.get_Address がエラーになるのか?
  → 具体的なエラー内容を記述してください。

☆得られたアドレスが、期待している結果と異なるのか?
  → どのような結果を期待していて、実際にはどうなってしまうのかを
   記述してください。


以下、細かい点について:

> oWBook = (Excel.Workbook)(oApplication.Workbooks.Open(
まずここで NG。後から ReleaseComObject の呼び出しを行うために、
Workbooks コレクションのインスタンスを変数に保持しておいてください。


> Type.Missing, // (省略可能)Converter
> Type.Missing, // (省略可能)AddToMru
> Type.Missing, // (省略可能)Local
> Type.Missing // (省略可能)CorruptLoad
> ));
ということは、Excel 2002/2003/2007 をお使いなのですね?
(Excel 97/2000 であれば、AddToMru までしか無いはずなので)


> oRange = oApplication.ActiveCell;
可能であれば、Active / Select 系のメンバには頼らない方が安全です。
「現在のセル」に対して操作するようなマクロ的な処理ならば仕方ないですが、
新たなブックを開いて、それに対して自動操作するような場合には、
どのブックの、どのシートの、どのセルを操作するのかを
具体的に記述する事ができないか、検討した方が良いかと。
不備があって申し訳ありません。

>>このとき開いているExcelのアクティブなセルのアドレスを得られません。
> こういう場合には、具体的な状況を記述した方が回答を得やすいですよ。
Excelのアドインから自分のプログラムを実行したいのですが、このプログラムをアクティブなセル上において(画像をはりつけるように)使うのに、そのセルのアドレスや内容が必要です。

しかし、以前に書いたプログラムで
t = oRange.get_Address(Type.Missing, Type.Missing, Excel.XlReferenceStyle.xlA1, Type.Missing, Type.Missing);
MessageBox.Show(t);

としてExcelからプログラムを呼び出すともう1つExcelが開いてしまい、その新しく開かれたExcelのアクティブセルのアドレスが表示されてしまいます。

> ☆oApplication.ActiveCell がエラーになるのか?
>   → 具体的なエラー内容を記述してください。
> ☆oApplication.ActiveCell が null を返すのか?
>   → そもそも、アクティブなセルがあるかどうかを確認してみてください。
>    たとえば(ワークシートではなく)グラフシートがアクティブになっている場合、
>    Application.ActiveCell は Nothing (C# では null)を返します。
>   → ワークシートがアクティブであるはずなのに、null を返すのであれば、
>    Visible = True にて Excel を表示させてから、再度チャレンジしてみてください。
oApplication.ActiveCellはnullではありませんでした。


>   → それでも駄目な場合は、一度 Window オブジェクトを経由させて、
>    そこから ActiveCell を得る事ができないかどうか、確認してみてください。
すみません、、「Windowsオブジェクトを経由」とは具体的にどういうことでしょうか?

> ☆oRange.get_Address がエラーになるのか?
>   → 具体的なエラー内容を記述してください。
> ☆得られたアドレスが、期待している結果と異なるのか?
>   → どのような結果を期待していて、実際にはどうなってしまうのかを
>    記述してください。
はじめにも書きましたが、既に起動しているExcel上のセルA1を選択してプログラムを実行すると、A1ではなく、そのとき新しく開かれたExcelのアクティブセルのアドレス(K7など…)が結果として出てきてしまいます。



>>oWBook = (Excel.Workbook)(oApplication.Workbooks.Open(
> まずここで NG。後から ReleaseComObject の呼び出しを行うために、
> Workbooks コレクションのインスタンスを変数に保持しておいてください。

> ということは、Excel 2002/2003/2007 をお使いなのですね?
不足があり申し訳ありません。Excel2007を使用しています。

よろしくお願いいたします。
■No23745に返信(andAさんの記事)
> としてExcelからプログラムを呼び出すともう1つExcelが開いてしまい、
> その新しく開かれたExcelのアクティブセルのアドレスが表示されてしまいます。
……あれ?
new Excel.Application() によって、もう 1 つのExcel を開くための
コードを書いていましたので、今回行いたいのは、Bookwork.xlsm 上の
セル位置だと思ったのですが、そうでは無いのですか?


Bookwork.xlsm 上のセル位置は関係なく、それ以前に開いていたブックの
セル位置が欲しいのであれば、新たに生成した Application インスタンスの
ActiveCell を拾うのではなく、「それ以前に開いていたブック」の
Application インスタンスを使ってください、『アドイン』であれば尚更です。


> Excelのアドインから自分のプログラムを実行したいのですが、
『アドイン』なのだとしたら、
 oApplication = new Excel.Application();
としてはマズイでしょう。現在開かれている Application と、
今作成した oApplication とは別のインスタンスなのですから。

新たなインスタンスを「作成」するのではなく、既存のインスタンスを「取得」しないと。


で。Excel アドインといっても、COM アドインや VSTO アドインなど、
幾つかの実装パターンがありますよね。
http://msdn.microsoft.com/ja-jp/library/aa830702.aspx
http://msdn.microsoft.com/ja-jp/library/ms173189%28VS.80%29.aspx
http://support.microsoft.com/kb/256624/ja


もし、VSTO アドインであれば、Globals.ThisAddIn.Application プロパティを
使って、現在開いている Excel.Application のインスタンスを得ることができます。

あるいは本当の意味での「アドイン」ではなく、実際には
http://support.microsoft.com/kb/302084/ja
のような、外部からのオートメーション操作を意図していたのであれば、
Microsoft.VisualBasic.Interaction.GetObject なり、Activator.GetObject なりを使って、
既に起動済みの Excel を得る必要があるかと思います。
(外部から操作する場合、Excel が複数起動されていた場合が問題となりますが…)


>   → それでも駄目な場合は、一度 Window オブジェクトを経由させて、
>    そこから ActiveCell を得る事ができないかどうか、確認してみてください。
> すみません、、「Windowsオブジェクトを経由」とは具体的にどういうことでしょうか?
Excel.Window と
Excel.Windows は別物ですが、それは兎も角として:

たとえば Excel 2007 で言えば、
 『表示』リボン(Alt + W)
  ┗『新しいウィンドウを開く』ボタン(N)
を使うと、同じブックを複数のウィンドウで開けますよね。
(「整列」ボタンで、それらのウィンドウを並べられます)


複数のウィンドウで開けば、この場合同じブックであっても、各ウィンドウごとに
選択位置を変更できますので、Excel.Application の ActiveCell の代わりに、
Excel.Window の ActiveCell を利用してはどうか、という意味で書きました。

もっとも、今回の問題は別の部分にあったようなので、この提案は無視してください。



>>ということは、Excel 2002/2003/2007 をお使いなのですね?
> 不足があり申し訳ありません。Excel2007を使用しています。
ファイルの拡張子が xlsm という時点で、2007 であることは
こちらで類推できたはずですね…読み漏らしていました。


――ところで、
>>> oWBook = (Excel.Workbook)(oApplication.Workbooks.Open(
>>> @"C:Bookwork.xlsm", // オープンするExcelファイル名
>>> Type.Missing, // (省略可能)UpdateLinks (0 / 1 / 2 / 3)
「C:\Bookwork.xlsm」(絶対パス指定)と、
「C:Bookwork.xlsm」(相対パス指定)とでは、
意味が異なりますが、その点は大丈夫でしょうか?
> new Excel.Application() によって、もう 1 つのExcel を開くための
> コードを書いていましたので、今回行いたいのは、Bookwork.xlsm 上の
> セル位置だと思ったのですが、そうでは無いのですか?
新しく開きたくなかったのですが、
http://oshiete1.goo.ne.jp/qa4597523.html
での回答を参考にした結果です。

object obj = Marshal.GetActiveObject("Excel.Application");
if (obj != null)
{
oApplication = (Excel.Application)obj;
}
oSheet = (Excel.Worksheet)oApplication.ActiveSheet;
oWBook = oApplication.ActiveWorkbook;
oRange = oApplication.ActiveCell;

としたところ思っていた結果を得ることが出来ました。
ありがとうございました。

> 「C:\Bookwork.xlsm」(絶対パス指定)と、
> 「C:Bookwork.xlsm」(相対パス指定)とでは、
> 意味が異なりますが、その点は大丈夫でしょうか?
個人名が入っていたので削除ミスです。
相対パスと絶対パスは大丈夫です。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板