お世話になります。
Visual Studio 2008 C# を使い、オートメーションで作成した Excel Book が閉じられたことを
リアルタイムで取得したいのです。
具体的には、フォームに複数のコントロールを配置した状態で、開いた Excel Book が閉じる瞬間をとらえてボタンの「Enabled」プロパティを制御できればいいのです。
簡単のために Excel Book はフォームの「Load」イベントで開き、新しい Book を追加します。
フォームにはボタン1個だけを配置します。
そして、Excel Book の右上の「×」ボタンで Book が閉じられる時、デリゲートを通じて
BeforeBookClose イベントを用意すれば、Book が閉じられるタイミングを捕まえることはできます。
問題は、以下のコードでは、C#の出力ウィンドウに
「Delegate: BookClose イベントが呼ばれました」
「button1.Enabled = False」
と表示され、button1 の「Enabled」プロパティも確かに「true」になります。
しかし、次の行は実行されず、出力ウィンドウには
「'System.InvalidOperationException' の初回例外が System.Windows.Forms.dll で発生しました。」と表示されています。
つまり、それ以下のコードは実行されていません。
さらには、フォームにボタンやコンボなどを1個でも追加すると、もう、「button1.Enabled = true;」も実行されなくなります。これが追加するのがラベルだけなら大丈夫でした。
BeforeBookClose イベントの処理は Excel Book に対して行われ、もとのC#のコントロールに対しては意味をなしていない、とも思いましたが一概にそうでもなさそうで混乱しています。
プロセス間通信とかスレッド間通信とかが必要なのか、よくわかりません。
よろしくお願いします。
namespace test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Excel.AppEvents_WorkbookBeforeCloseEventHandler EventDel_BeforeBookClose;
Excel.Application AppExcel = new Excel.Application();
private void Form1_Load(object sender, EventArgs e)
{
AppExcel.Visible = true;
Excel.Workbook WB = AppExcel.Workbooks.Add(Type.Missing);
EventDel_BeforeBookClose = new Excel.AppEvents_WorkbookBeforeCloseEventHandler(BeforeBookClose);
AppExcel.WorkbookBeforeClose += EventDel_BeforeBookClose;
button1.Enabled = false;
}
private void BeforeBookClose(Excel.Workbook Wb, ref bool Cancel)
{
System.Diagnostics.Debug.Print("Delegate: BookClose イベントが呼ばれました");
System.Diagnostics.Debug.Print("button1.Enabled = " + button1.Enabled.ToString());
button1.Enabled = true;
System.Diagnostics.Debug.Print("button1.Enabled = " + button1.Enabled.ToString());
AppExcel.WorkbookBeforeClose -= EventDel_BeforeBookClose;
}
}
}
No.1ベストアンサー
- 回答日時:
ご考察の通り 異なるスレッド(プロセス)間のイベントのために引き起こされている現象だと思います
ボタンのEnabledプロパティおよび BeforeBookCloseのイベント削除用のハンドラを別に用意します
これを Delegateを通して Invokeで呼び出してあげればいいようです
private void myEnabelMethod()
{
// これらの操作をするスレッドが違うと処理が続行されない
// Excel側で例外を吸収してしまっているのかも
// 以下の処理順は どちらが先でもOKなようです
button1.Enabled = true;
AppExcel.WorkbookBeforeClose -= EventDel_BeforeBookClose;
}
private Delegate void myEnabled();
private myEnabled myDelgateEnabled;
Form_Loadイベントやコンストラクタで
myDelegateEnabeld = new myEnabled( myEnabledMethod );
を実行しておく
BefotreBookCloseイベントで
Invoke( myDelegateEnabeld );
を実行
といった具合でいいと思います …
ありがとうございました。
なんとなく Invoke にはたどりついていたのですが、具体的な使い方がわかりませんでした。
以下のコードでばっちりでした。とても助かりました。ありがとうございました。
using System;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
namespace ExcelEventTest成功
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private delegate void myEnabled();
private myEnabled myDelegateEnabled;
Excel.AppEvents_WorkbookBeforeCloseEventHandler EventDel_BeforeBookClose;
Excel.Application AppExcel;
private void myEnablMethod()
{
button1.Enabled = true;
AppExcel.WorkbookBeforeClose -= EventDel_BeforeBookClose;
}
private void BeforeBookClose(Excel.Workbook Wb, ref bool Cancel)
{
/*
* ここに C# のフォームに対する処理を記述しても動作しない。
* 異なるプロセス間の通信だからだと思われる。
*
* そこで、Invoke により解決を図る。
*
* しかし、このアプリが無事終了しないと、オバケの Excel は残る。
*
*/
System.Diagnostics.Debug.Print("Delegate: BookClose イベントが呼ばれました");
Invoke(myDelegateEnabled);
}
private void Form1_Load(object sender, EventArgs e)
{
myDelegateEnabled = new myEnabled(myEnablMethod);
EventDel_BeforeBookClose = new Excel.AppEvents_WorkbookBeforeCloseEventHandler(BeforeBookClose);
button1.Enabled = true;
}
private void button1_Click(object sender, EventArgs e)
{
AppExcel = new Excel.Application();
AppExcel.Visible = true;
Excel.Workbook WB = AppExcel.Workbooks.Add(Type.Missing);
AppExcel.WorkbookBeforeClose += EventDel_BeforeBookClose;
button1.Enabled = false;
}
}
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C# DatagridviewにExcelシートを反映するとエラーが出る 2 2023/05/06 17:12
- その他(プログラミング・Web制作) pythonでクラスで複数のメソッドを利用する方法 2 2022/04/15 04:17
- JavaScript 入力フォームの javascript で メールアドレスの正規チェックをを行い、ボタンをクリックして 2 2022/04/27 16:06
- C言語・C++・C# Windows Formアプリからコンソールを呼び出して文字を出力させたい 8 2023/05/09 10:53
- JavaScript Javascriptが機能せず原因が分からないので教えて頂きたいです 3 2023/06/04 14:50
- Excel(エクセル) EXCEL ActiveX コマンドボタンで実行する前にいったんmsgBoxで確認を求めたい 1 2022/07/06 19:41
- Visual Basic(VBA) 複数のcsvファイルをExcelに一括変換したい 2 2023/03/03 12:44
- その他(データベース) Accessフォームからパラメーターで表示したレコードを指定のExcelのセルへ転送する方法について 2 2022/08/22 18:04
- HTML・CSS ボタンをクリックした時に、入力フォームのすぐ下部に、「入力欄が空白です」というテキストメッセージが表 1 2022/04/27 16:25
- JavaScript ①入力フォーム→②確認表示画面→③送信完了画面のコードを書いているのです、 入力フォームから受け取っ 2 2022/05/10 16:45
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VB.NETでのイベントの途中終了
-
VBAでcallで呼び出したsubを終...
-
他のフォームから別のフォーム...
-
チェックボックスを操作できな...
-
コンボボックスのClickイベント
-
【VB6.0】 あるフォームから他...
-
C#のループでtextboxに値を入れ...
-
二点の座標から距離や角度を求...
-
エクセルVBAでテキストボッ...
-
C言語のサフィックスについて
-
pthread_cond_waitとptherad_co...
-
VC++ (byte)(col & 0xFF) の意味
-
Pythonでのstrip()とsplit()の...
-
perlによるxmlファイルの取得
-
sublimit textっていうエディタ...
-
レコードセットにnullの場合
-
C言語で10行10列の行列式の値を...
-
タイムアウトする仕組みを作りたい
-
String型の値にスラッシュをつ...
-
アクセスできない保護レベルエ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
VBAでcallで呼び出したsubを終...
-
他のフォームから別のフォーム...
-
VB.NETでのイベントの途中終了
-
チェックボックスを操作できな...
-
ClickとChangeイベントの違いは...
-
VB6でClickイベントを一時的に...
-
[Excel2000]auto_closeを止めさ...
-
VB6でForm_Load中にイベントを...
-
comboboxのクリックイベントに...
-
EXCEL2010 VBA SelectionChange...
-
コンボボックスのClickイベント
-
WORDのアドイン
-
三項でたとえば交換って
-
VBA public変数はどのようなこ...
-
C#のループでtextboxに値を入れ...
-
C言語のサフィックスについて
-
レコードセットにnullの場合
-
エクセルVBAでテキストボッ...
-
Functionの戻り値を配列にした...
-
プログラムの素朴な質問です 分...
おすすめ情報