トップ回答者
エクセルのBeforeCloseイベントで他の非表示ブックを表示させると

質問
-
複数のブックを開いてVBAで処理を行うプログラムを組んでいるときに奇妙な現象が起きました。
下記のようにマクロを書いたBook1とBook2を開らきます。
ただし、Book2はWorkbook_Openで非表示にしています。
Book1を閉じた時にBook2を表示させたいので、
Book1のBeforeCloseイベントでWindows(Book2.xlsm).Visible = Trueという処理を追加しました。
すると下記のような現象が起きました。
下に詳しいプログラムを提示してあります。それ以外のプログラムはこれらブックに書いていません。
プログラム上のミスがあればご教授いただきたいです。
また、このような現象を起こさないような方法があればこれもご教授いただきたいです。
Windows10 64Bit
Excel 2016
上記二つのブック以外はエクセルで開いていません
Book1.xlsmのWorkbook_BeforeCloseイベント
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim wb As Workbook
For Each wb In Workbooks
If wb.Name = "Book2.xlsm" Then
Application.Windows("Book2.xlsm").Visible = True
Exit Sub
End If
Next
End Sub
Book2.xlsmのWorkbook_Openイベント
Private Sub Workbook_Open()
Application.Windows(ThisWorkbook.Name).Visible = False
End Sub
手順1:
Book1を立ち上げたあと、Book2を立ち上げる。その後ウインドウ右上の×ボタンをクリック
結果:Book2が表示されアクティブウインドウとなる。Book1は閉じない。
その後① Book1をアクティブにし、×をクリック
→Book1は閉じる。
その後② Book2を非表示にする
→Book1がアクティブになる。×をクリック
→Book2に関する警告表示(保存するか?)
→1.「保存する」または「しない」をクリック
→Book1、Book2ともに閉じられる。
→2.キャンセルをクリック
→何も起こらない
→その後×をクリック
→手順2と同じ結果
手順2:
Book2を立ち上げた後(このときBook2は非表示)、Book1を立ち上げる。その後×をクリック
結果:Book2はアクティブになるが全画面表示(リボン、×ボタン等が表示されない)のようになる。Book1は閉じない。その後Book1をアクティブにし、×をクリックするとBook1は閉じる。Book2については全画面表示の解除方法がわからないので、タスクマネージャーから強制終了。
- 編集済み Joe_Hide 2018年7月5日 4:41 正しく伝えられない可能性があったため
回答
-
「全画面表示のように」は私の方でも再現しておりました。ただ、Book2自体がおかしくなっていたように思い、一度、起動時に非表示にしないようにして立ち上げ、再度、起動時に非表示にするなどすると、知らぬ間に直っていました。これは手順1での話です。
今、再度、手順2を行ってみましたが、おっしゃるように「全画面表示のように」なってしまいますね。
ただ、先にBook2を立ち上げると、私のところでは非表示にはならなくて、シートが全くないExcelが表れています。これは、Book2は非表示なのですが、大元のExcelというか、そういう感じのものが開いているようです。その後、Book1を立ち上げるとBook1の状態だけとなります。何となく先ほどの大元のExcelにBook1が表示された感じがします。C#からExcelを操作する際に、OpenXmlというものがあります。これはExcelの構造を知っていないと扱えないのですが、その際に、SpreadsheetDocumentというオブジェクトを生成し、そこにWorkBookオブジェクトなどが属するようになります。つまり、大元に見えているこのExcelがSpreadsheetDocumentオブジェクトではないかと想像しています。
#ちなみにOpenXmlは面倒なので、それをラップしたClosedXmlを使った方がはるかに楽です。手順2に関してですが、仕組みはよくわかりませんが、以下のコードをBook1に追加するとうまく動いているようです。
Private Sub Workbook_Open() Dim wb As Workbook For Each wb In Workbooks If wb.Name = "Book2.xlsm" Then Application.Windows("Book2.xlsm").Visible = True Application.Windows("Book2.xlsm").Visible = False Exit For End If Next End Sub
う~ん、やっぱり完全にわかってないなぁ。
★良い回答には質問者は回答済みマークを、閲覧者は投票を!
- 編集済み trapemiyaModerator 2018年7月6日 11:46 コード修正
- 回答としてマーク Joe_Hide 2018年7月7日 1:16
すべての返信
-
確かにちょっとよくわからない動作をしますね。以前からのようです。
Excelを編集した後、Bookを非表示にして保存
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12124503442Application.Windowsで全てのBookが参照できるように、Excelのブックはそれぞれ独立しているのではなく、どこかで一括して管理されているようですね。おそらくその関係で意図した通りにならないのだと思います。
とりあえず対処療法ですが、以下のコードで何となく実現できている雰囲気です。'下のApplication.Windows(ThisWorkbook.Name).Closeで発生した2回目のWorkbook_BeforeCloseは何もせずに抜ける If Application.Windows("Book2.xlsm").Visible = True Then Exit Sub End If Dim wb As Workbook For Each wb In Workbooks If wb.Name = "Book2.xlsm" Then Application.Windows("Book2.xlsm").Visible = True Application.Windows(ThisWorkbook.Name).Close Cancel = True Exit For End If Next End Sub
(補足)
上のコードは、要するにBook1を閉じる動作と、Book2を表示する動作を分けることを意図しています。
Book2を表示した後にBook1を閉じる動作をキャンセルし、その後、Book1を改めて閉じる動作となります。
★良い回答には質問者は回答済みマークを、閲覧者は投票を!
- 編集済み trapemiyaModerator 2018年7月6日 2:59 補足を追記
-
ご返信ありがとうございます。
ご提示いただいたコードで実行してみたら、Book1を閉じることができました。
ただ、手順2を実行するとBook2は「全画面表示のように」なってしまいました。
最初の投稿で私の表現が悪かったので誤解させてしまったようです。申し訳ありません。
「全画面表示のように」とは、「タイトルバー、リボン(メニューバー)、ステータスバー」が表示されない、という状況です。これは通常のエクセルの全画面表示ではありません。ウインドウを最大化しないで手順2を実行するとウインドウの大きさはそのままで、「タイトルバー、リボン(メニューバー)、ステータスバー」が表示されない状態になります。通常の全画面表示ではESCキーを押すと全画面表示が解除になるはずですが、それもできません。
もしかしたら、私のエクセルやパソコンの不具合が原因でこの状態になるかも知れません。私のエクセルを再インストールしてからもう一度ご提示いただいたコードを実行してみます。
本当にご返答ありがとうございました。
-
「全画面表示のように」は私の方でも再現しておりました。ただ、Book2自体がおかしくなっていたように思い、一度、起動時に非表示にしないようにして立ち上げ、再度、起動時に非表示にするなどすると、知らぬ間に直っていました。これは手順1での話です。
今、再度、手順2を行ってみましたが、おっしゃるように「全画面表示のように」なってしまいますね。
ただ、先にBook2を立ち上げると、私のところでは非表示にはならなくて、シートが全くないExcelが表れています。これは、Book2は非表示なのですが、大元のExcelというか、そういう感じのものが開いているようです。その後、Book1を立ち上げるとBook1の状態だけとなります。何となく先ほどの大元のExcelにBook1が表示された感じがします。C#からExcelを操作する際に、OpenXmlというものがあります。これはExcelの構造を知っていないと扱えないのですが、その際に、SpreadsheetDocumentというオブジェクトを生成し、そこにWorkBookオブジェクトなどが属するようになります。つまり、大元に見えているこのExcelがSpreadsheetDocumentオブジェクトではないかと想像しています。
#ちなみにOpenXmlは面倒なので、それをラップしたClosedXmlを使った方がはるかに楽です。手順2に関してですが、仕組みはよくわかりませんが、以下のコードをBook1に追加するとうまく動いているようです。
Private Sub Workbook_Open() Dim wb As Workbook For Each wb In Workbooks If wb.Name = "Book2.xlsm" Then Application.Windows("Book2.xlsm").Visible = True Application.Windows("Book2.xlsm").Visible = False Exit For End If Next End Sub
う~ん、やっぱり完全にわかってないなぁ。
★良い回答には質問者は回答済みマークを、閲覧者は投票を!
- 編集済み trapemiyaModerator 2018年7月6日 11:46 コード修正
- 回答としてマーク Joe_Hide 2018年7月7日 1:16
-
再びのご返信ありがとうございます。
望み通りに動きました。
ただ、別の問題が発生しました。
パソコンにこのブックを保存させている場合は何も問題はありません。が、OneDrive上だと下記のようになります。
私はこの二つのブックをOneDrive上に保存しています。後だしのようになってしまってすみません。私はここに保存していることで問題が起きるとは毛頭も思っていなかったので、最初の投稿には記述しませんでした。
ご提示いただいたコードを追加したブックをOneDrive上に保存して、Book1,Book2を開きます。Book1が表示された状態で×ボタンをクリックすると、通常にBook2が表示されます。このとき×ボタンをクリックすると以下のメッセージが表示されます(手順1,2ともに)。
タイトルバーに「Microsoft Excel」 アイコン「?」
「他のユーザーと結合できない変更がサーバー上にあります。続けるにはサーバー上の変更内容を破棄するか、ファイルのコピーを保存してください。」
ボタン「サーバー上の変更を破棄する」「コピーを保存」「キャンセル」
OneDriveには私しかアクセスできません。また他のパソコンから私がBook2を変更していたわけでもありません。
ただ、私はネットワークに詳しくないので、設定など正しく行っていない可能性があります。
このようなことがあった、ということを情報として上げておきたいと思います。
また、この問題はまた投稿したものとは異なるものなので、回答としてマークさせていただきます。
trapemiya様,お付き合いいただきありがとうございました。