C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[1]: 二度エクセルを開かない


(過去ログ 176 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■100944 / inTopicNo.1)  二度エクセルを開かない
  
□投稿者/ まさちん (1回)-(2022/12/03(Sat) 09:39:49)

分類:[C#] 

教えて下さい

c#のフォームから任意のエクセルを開くまでは行ったのですが
もう一度開くボタンを押してしまうと多重にエクセルが開いてしまいます

一度開いたらボタンを押しても多重に開かないようにするには
if文をどう書けばよろしいでしょうか
宜しくお願い致します
引用返信 編集キー/
■100945 / inTopicNo.2)  Re[1]: 二度エクセルを開かない
□投稿者/ とっちゃん (771回)-(2022/12/03(Sat) 15:55:52)
No100944 (まさちん さん) に返信
> 教えて下さい
>
> c#のフォームから任意のエクセルを開くまでは行ったのですが
> もう一度開くボタンを押してしまうと多重にエクセルが開いてしまいます
>
> 一度開いたらボタンを押しても多重に開かないようにするには
> if文をどう書けばよろしいでしょうか
> 宜しくお願い致します

自分で押す前に起動していた場合は、起動してもいいのでしょうか?
それともその場合も起動しないのがいいのでしょうか?

それによっても判断基準が変わります。

自分で2個起動しないというだけであれば、
ボタンを押したことを覚えておいて(フラグを作る)それで判定すればよいと思います。

自分で起動していないものも含めて複数立ち上がっていたらNGとするなら
すでにExcelが起動しているかを判定するコードが必要です。

どうやって起動しているかで変わってくるので、そのあたりはご自身で作っている
コードからリファレンスなどをたどって確認してください。

引用返信 編集キー/
■100946 / inTopicNo.3)  Re[1]: 二度エクセルを開かない
□投稿者/ 魔界の仮面弁士 (3502回)-(2022/12/04(Sun) 10:19:48)
No100944 (まさちん さん) に返信
> c#のフォームから任意のエクセルを開くまでは行ったのですが
C# のことが
c# と書かれていることに違和感がありますが、それはさておき。


エクセルを開く、とのことですが、現状がどのようなコードで
開いているのかを示してもらわないことには、それをどのように
訂正すべきかを指摘することさえできません。現在の起動方法を教えてください。


Process.Start(xlsxファイルのフルパス); で開いているのでしょうか。

Process.Start(Excelのフルパス, xlsxのフルパス); で開いているのでしょうか。
https://support.microsoft.com/ja-jp/office/079164cd-4ef5-4178-b235-441737deb3a6#Category=Excel

あるいは、Excel.Application を呼び出しているのでしょうか。
https://qiita.com/tomohideyo/items/f46eab04b86316d917c5

それとも Microsoft.VisualBasic.Interaction.GetObject を呼び出しているのでしょうか。
https://qiita.com/nukie_53/items/12cc0a3fc295a446a045

System.Runtime.InteropServices.Marshal.GetActiveObject を使うという手もありますよね。
https://learn.microsoft.com/ja-jp/dotnet/api/system.runtime.interopservices.marshal.getactiveobject?view=netframework-4.8

> もう一度開くボタンを押してしまうと多重にエクセルが開いてしまいます
・Excel 2010 までは MDI を選択できましたが、2013 以降は SDI のため、複数のファイルを開けば、Excel 画面も複数開かれます。
https://learn.microsoft.com/ja-jp/office/vba/excel/concepts/programming-for-the-single-document-interface-in-excel

・通常はたとえ別フォルダーにあるファイルであったとしても、同じ名前のファイルは同時に複数開けませんが
 Excel.exe の別インスタンスを明示的に開いている場合には、同名ファイルを多重に開くことができます。
https://www.a-ibs.com/blog/---excel/excel.html


> 一度開いたらボタンを押しても多重に開かないようにするには
button1.Enabled = false; にすることで、ボタンを押せなくすることが可能です。

それともボタン以外に、ユーザー操作によって Excel アプリケーションが起動されたり、
あるいは .xlsx ファイルをダブルクリックで起動されることもあるでしょうが、
そうした呼び出しに対しても対処が必要ということなのでしょうか。


Excel が起動済みかどうかだけを調べるなら、Process.GetProcessesByName メソッドを使えます。
https://anond.hatelabo.jp/20150810121732

Excel が起動されているかどうかではなく、そこで特定のワークブックが開かれているかを
調べたいのであれば、ROT を辿って起動済みの Workbook オブジェクトを取得し、
FullName プロパティを確認すればよいでしょう。
https://qiita.com/nukie_53/items/5d681a2f49a137204c14

起動済みかどうかを調べた上で、既に開かれているワークブックにたいして
Excel.Application を取得してセルの読み書きなどの操作を行いたいという目的であれば
Microsoft.VisalBasic.Interaction.GetObject(Type.Missing, xlsxファイルのするパス) を使う方法もあります。
https://learn.microsoft.com/ja-jp/dotnet/api/microsoft.visualbasic.interaction.getobject?view=netframework-4.8
引用返信 編集キー/
■100947 / inTopicNo.4)  Re[2]: 二度エクセルを開かない
□投稿者/ まさちん (2回)-(2022/12/04(Sun) 18:30:47)
No100946 (魔界の仮面弁士 さん) に返信

ありがとうございます

 private void btnOpen_Click(object sender, EventArgs e)
        {
            excelApp = new Excel.Application();
            wb = excelApp.Application.Workbooks.Open(@"c:\DATA\メカ" + txtFileName.Text + ".xlsx");
            ws = (Excel.Worksheet)excelApp.Worksheets[1];
            excelApp.Application.Visible = true;
        }

上記でエクセルを開いています
button1.Enabled = false でボタンを押せなくすることも考えたのですが
エクセルの方で終了してしまうとボタンを押せないままになるので
開いたと言う事を確認できる方法はないでしょうか

引用返信 編集キー/
■100949 / inTopicNo.5)  Re[3]: 二度エクセルを開かない
□投稿者/ 大谷刑部 (221回)-(2022/12/05(Mon) 10:27:56)
No100947 (まさちん さん) に返信
> ■No100946 (魔界の仮面弁士 さん) に返信
> エクセルの方で終了してしまうとボタンを押せないままになるので
> 開いたと言う事を確認できる方法はないでしょうか
>

それもすでに弁さんが回答済みなんでは?

>>Excel が起動済みかどうかだけを調べるなら、Process.GetProcessesByName メソッドを使えます。
>>https://anond.hatelabo.jp/20150810121732
>>
>>Excel が起動されているかどうかではなく、そこで特定のワークブックが開かれているかを
>>調べたいのであれば、ROT を辿って起動済みの Workbook オブジェクトを取得し、
>>FullName プロパティを確認すればよいでしょう。
>>https://qiita.com/nukie_53/items/5d681a2f49a137204c14
>>
>>起動済みかどうかを調べた上で、既に開かれているワークブックにたいして
>>Excel.Application を取得してセルの読み書きなどの操作を行いたいという目的であれば
>>Microsoft.VisalBasic.Interaction.GetObject(Type.Missing, xlsxファイルのするパス) を使う方法もあります。
>>https://learn.microsoft.com/ja-jp/dotnet/api/microsoft.visualbasic.interaction.getobject?view=netframework-4.8

要はボタンクリック処理の最初にExcelのプロセスが既にいたらreturnするようにして、
enableプロパティーと併用するなら、タイマーコントロールとかを使って、プロセスなくなったらtrueにして押せるようにするとかでよいかと。

引用返信 編集キー/
■100950 / inTopicNo.6)  Re[3]: 二度エクセルを開かない
□投稿者/ 魔界の仮面弁士 (3503回)-(2022/12/05(Mon) 11:18:06)
No100947 (まさちん さん) に返信
> excelApp = new Excel.Application();
> wb = excelApp.Application.Workbooks.Open(@"c:\DATA\メカ" + txtFileName.Text + ".xlsx");
> excelApp.Application.Visible = true;

.Application が返すオブジェクトは Excel.Application 型そのものなので、この場合の
 excelApp.Application.Workbooks
 excelApp.Application.Visible
は Application プロパティが冗長です。不要なプロパティ参照を削って、
 excelApp.Workbooks
 excelApp.Visible
としましょう。


また、「excelApp.Workbooks.Open」や「excelApp.Worksheets[1]」のような書き方をすると
COM オブジェクトである Workbooks オブジェクトや Sheets オブジェクトの解放漏れに繋がります。
個々の COM オブジェクトを変数に受け取っておき、オブジェクトの使用後は、
それらの COM オブジェクトを『Marshal.ReleaseComObject メソッド』に渡して解放すべきです。


if (excelApp == null) {
  this.excelApp = new Excel.Application();

  // .NET から COM オブジェクトを操作するときは、
  // 利用した COM オブジェクトすべてを変数に受ける必要がある
  this.books = excelApp.Workbooks;
  this.book = books.Open(@"c:\DATA\メカ" + txtFileName.Text + ".xlsx");
  this.sheets = book.Worksheets;
  this.ws = (Excel.Worksheet)sheets[1];

  // ユーザーからの干渉を防ぎたい(キーボードやマウス操作を受け付けないようにしたい)場合は false にする
  // this.Interactive = false;
  // Excel を表示する場合は true にする
  this.Visible = true;

  // イベント割り当てを行うこともできるが、終了前には -= で解除せねばならない。
  // this.NewWorkbook += app_NewWorkbook;
  // this.WorkbookOpen += app_WorkbookOpen;
  // this.WorkbookAfterSave += app_WorkbookAfterSave;
}


> button1.Enabled = false でボタンを押せなくすることも考えたのですが
> エクセルの方で終了してしまうとボタンを押せないままになるので

どこまで監視したいのでしょうか?
そもそも、C# を起動する前に、該当の .xlsx ファイルをすでに開いていた…という場合もあるはずですよね。

Excel のユーザー操作を許可しているなら、C# から開いたブックが別のファイル名で保存されることもありますし、
あるいはその起動済みの Excel 上で、さらに別のワークブックを開くこともできます。さらに言えば、
その別ブックのファイル名を、@"c:\DATA\メカ" + txtFileName.Text + ".xlsx" の名で上書き保存することさえできます。


ワークブックが開かれたり保存されたりしたことを捕らえたいのであれば、
Excel.Application オブジェクトのイベントを使って知ることができます。

また、ユーザーによって Excel が終了された場合、Excel が使用中と判断されて
タスク マネージャー上で「非表示」のままゾンビのまま生き残るパターンもあれば、
C# 側でオブジェクトを掴んだまま、Excel 本体が終了してしまっているケースもあります。

Excel インスタンスが生き残っている場合は、ウィンドウが非表示になっているだけであり、
そのままプログラムから制御可能でしょう。

あるいは Excel 本体が既に終了済みの場合は、C# から Excel のメソッドやプロパティを
操作しようとした段階で実行時エラーになるため、それを try〜catch でつかまえてから
あらためて Excel インスタンスを再生成するといった手順になります。


自身の C# アプリ以外から手動で開かれた .xlsx ファイルを捕らえたい場合は、
No100946 で紹介した Running Object Table なり GetObject を使えばよいわけで。
引用返信 編集キー/
■100960 / inTopicNo.7)  Re[1]: 二度エクセルを開かない
□投稿者/ furu (186回)-(2022/12/05(Mon) 18:55:24)
No100944 (まさちん さん) に返信
> 一度開いたらボタンを押しても多重に開かないようにするには
> if文をどう書けばよろしいでしょうか
至極安易な方法として
そのエクセルがファイルオープンできるか確認してみてもいいと思います。

try
{
    using (new System.IO.FileStream(
                    @"c:\DATA\メカ" + txtFileName.Text + ".xlsx",
                    System.IO.FileMode.Open,
                    System.IO.FileAccess.ReadWrite,
                    System.IO.FileShare.None))
    {}
}
catch
{
    MessageBox.Show("既に開いているかも");
    return;
}

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -