【会員アンケートご協力のお願い】抽選で計5名様に役立つ書籍をプレゼント!

Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 10 Home : Excel 2013)
Workbook_BeforeCloseにて印刷を実行したい
投稿日時: 24/10/21 13:05:12
投稿者: ichibaMan

'''book2 Thisworkbook モジュール
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim sh As Worksheet
For Each sh In Me.Worksheets
    sh.PrintPreview
Next
Me.Saved = True
MsgBox "ByeBye"
End Sub
 
'''book1 標準モジュール
Sub test()
Dim wb As Workbook
Set wb = Workbooks.Open(Filename:=ThisWorkbook.Path & "\Book2.xlsm")
wb.Close
Set wb = Nothing
End Sub
 
book2 を手動で開き、閉じると正しくプリントプレヴューし、メッセージ表示後閉じられますが、
book1 のマクロ test より実行するとプリントプレヴューされず、メッセージのみで閉じられてしまいます。
(とりあえず、テストでプレヴューにしています)
book1 のマクロからでもbook2終了時プリント(プレヴュー)させたいのですが、、、、
ご教授くださいませ。。

回答
投稿日時: 24/10/21 18:05:38
投稿者: simple

Excel365でも再現しますね。原因は不明です。
(1)表示されていないのか、
(2)表示されているが、ユーザーアクションを待たせることがスキップされているのか
画面がちらちらしないので、たぶん(1)のような気はしますけれども。
 
感想をメモします。(原因解明には貢献しませんけれども)
・BeforeCloseイベントプロシージャで印刷プレビューさせるという仕組みが、ちょっと悪手なのかもしれません。
 
・特に他のブックから開いて、マクロでなんらかの処理をさせる場合は、
プレビューするプロシージャーを標準モジュールに独立させておいて、
その処理の最後で明示的に、Application.Runでそのプレビュープロシージャを実行する、
というのが安全確実でしょう。
 
・加えて、closeのつどプレビューするのも、うざくなる時もあるのではないかと思います。
単に閲覧しただけのときもあるので。
必要な時にプレビューのプロシージャを意図的に実行する、という作りのほうが良いと思います。

回答
投稿日時: 24/10/21 18:06:06
投稿者: WinArrow

この事象については、こちらでも再現しました。
Windows10 & Excel2019
ステップ実行の結果、
PrintPreviewコードが実行されてはいるが、画面表示されないという不思議n現象ですね?
原因は、よくわかりません
  
回答になっていなくてすみません。
 

回答
投稿日時: 24/10/21 21:54:56
投稿者: WinArrow

BOOK1ががテストということなのですが、
 
代案を紹介します。
 
BeforeCloseプロシジャのコードを標準モジュールに移動します。
(BeforeCloseは削除、標準モジュール側のプロシジャ名を理に「PRINTSUB」とします)
 
Book1側に
 RUN wb.Name & "!PRINTSUB"
を、
wb,Closeの前に記述
 

回答
投稿日時: 24/10/22 10:38:03
投稿者: sk

引用:
Workbook_BeforeCloseにて印刷を実行したい

引用:
For Each sh In Me.Worksheets
    sh.PrintPreview
Next

何の条件もなしに、毎回ブックを閉じる時に
そのブックの全てのワークシートを印刷する、
というオペレーションの意義がよく分からない点は
とりあえず置いておくとして。
 
引用:
book1 のマクロ test より実行するとプリントプレヴューされず、
メッセージのみで閉じられてしまいます。
(とりあえず、テストでプレヴューにしています)

こちらの環境で試した限り、PrintPreview メソッドだけでなく
(本来実行しようとしている)PrintOut メソッドも実行されませんね。
 
( Book2.xlsm のブックモジュール)
---------------------------------------------------------------
Private Sub Workbook_BeforeClose(Cancel As Boolean)
 
Dim sh As Worksheet
For Each sh In Me.Worksheets
    '紙がもったいないので出力先を PDF プリンタにして印刷
    sh.PrintOut ActivePrinter:="Microsoft Print to PDF", _
                PrintToFile:=True, _
                PrToFileName:=Me.Path & "\" & sh.Name & ".pdf"
Next
Me.Saved = True
MsgBox "ByeBye"
 
End Sub
---------------------------------------------------------------
 
Worksheet オブジェクトだけではなく Workbook オブジェクトの
PrintOut / PrintPreview メソッドについても同様。
 
ちなみに ExportAsFixedFormat メソッドによって
PDF 出力する分には問題ありませんでした。
 
( Book2.xlsm のブックモジュール)
---------------------------------------------------------------
Private Sub Workbook_BeforeClose(Cancel As Boolean)
 
Dim sh As Worksheet
For Each sh In Me.Worksheets
    sh.ExportAsFixedFormat xlTypePDF, Me.Path & "\" & sh.Name & ".pdf"
Next
Me.Saved = True
MsgBox "ByeBye"
 
End Sub
---------------------------------------------------------------
 
また、Workbook_BeforeClose イベントプロシージャを使用せず
Book2.xlsm の標準モジュールに Auto_Close マクロを記述し、
Book1.xlsm 側のマクロから明示的に呼び出す場合は
PrintOut / PrintPreview 共に有効でした。
 
( Book2.xlsm の標準モジュール)
---------------------------------------------------------------
Sub Auto_Close()
 
Dim sh As Worksheet
For Each sh In ThisWorkbook.Worksheets
    sh.PrintPreview
Next
ThisWorkbook.Saved = True
MsgBox "ByeBye"
 
End Sub
---------------------------------------------------------------
 
( Book1.xlsm の標準モジュール)
---------------------------------------------------------------
Sub test2()
Dim wb As Workbook
Set wb = Workbooks.Open(Filename:=ThisWorkbook.Path & "\Book2.xlsm")
wb.RunAutoMacros xlAutoClose
wb.Close False
Set wb = Nothing
End Sub
---------------------------------------------------------------

回答
投稿日時: 24/10/22 14:49:26
投稿者: rie1234k

book2のWorkbook_BeforeCloseを正常に動作させたいということであれば、book2のThisworkbookモジュールに以下のマクロ CloseEvent を追加します。
そのマクロをbook1のマクロ test より起動し、マクロ testでのbook2を閉じる際のイベントの発生は無効にしてみてはどうでしょうか?
 
'book2 Thisworkbook モジュール

Public Sub CloseEvent() '追加

    Call Workbook_BeforeClose(True)

End Sub

 
'book1 標準モジュール
Sub test() '修正版

Dim wb As Workbook

    Set wb = Workbooks.Open(FileName:=ThisWorkbook.Path & "\Book2.xlsm")
    
    Application.Run wb.Name & "!Thisworkbook.CloseEvent" '追加したCloseEventを起動
    
    Application.EnableEvents = False 'イベントの発生を無効化
    
    wb.Close
    
    Application.EnableEvents = True  'イベントの発生を有効化
    
    Set wb = Nothing

End Sub

 
マクロからブックを操作して閉じた場合、操作しているブックのWorkbook_BeforeClose内では、ブックやシート関連の操作ができないという事例はあるようです。
その場合、ブックモジュール内にWorkbook_BeforeCloseを呼び出すマクロを作成し、ブックを操作して閉じるマクロから、作成したマクロを呼び出すようにすることで、正常に操作が可能なようです。

投稿日時: 24/10/23 06:54:10
投稿者: ichibaMan

皆様、検証、助言、ありがとうございます。
非常に勉強になります。感謝です。
 
この度、提示させて頂いたコードは検証の為、省略したもので
何かと不審かとは思われますが、お付き合いいただきありがとうございました。
 
皆様の助言をもとに以下の通り Application.Run にて実行する形に落ち着きました。
ひとまず解決とさせて頂きます。
 
'''book1 標準モジュール
Sub test_2()
Dim wb As Workbook
 
Set wb = Workbooks.Open(Filename:=ThisWorkbook.Path & "\Book2.xlsm")
Application.Run wb.Name & "!Thisworkbook.CloseAfterPrg"
Set wb = Nothing
 
End Sub
 
 
'''book2 Thisworkbook モジュール
Sub CloseAfterPrg()
Dim sh As Worksheet
For Each sh In Me.Worksheets
    sh.PrintPreview
Next
MsgBox "ByeBye"
Me.Close SaveChanges:=False
End Sub