Excel (VBA)

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

 
(Windows 10 Home : Excel 2010)
ブック印刷で特定のシートの印刷前に処理をしたい
投稿日時: 17/12/16 11:25:36
投稿者: pyonpyon

シート1、シート2、シート3があるブックをブック印刷した時、シート1、シート2の印刷完了後、シート3を印刷する直前に制御を受けて処理をしたいので、Workbook_BeforePrintで制御を受けActiveSheet.Nameでシート名を参照したのですが、シート1しか参照できませんでした(^^;
ご教示よろしくお願いします。

回答
投稿日時: 17/12/16 11:32:25
投稿者: simple

実行したコードを示してください。

回答
投稿日時: 17/12/16 15:28:34
投稿者: WinArrow
投稿者のウェブサイトに移動

ブック印刷を、シート印刷に変更して連続印刷したらよいでしょう。

回答
投稿日時: 17/12/16 17:50:34
投稿者: WinArrow
投稿者のウェブサイトに移動

ブック印刷する前に
シート3の処理をすればよいでしょう。

回答
投稿日時: 17/12/16 20:34:33
投稿者: もこな2

やりたいことがよくわからないです
手動でシート1、シート2を印刷して、何か処理をマクロで行ってからシート3を手動で印刷したいのでしょうか?初めから、全部マクロ化してはだめなんでしょうか?

投稿日時: 17/12/17 09:21:52
投稿者: pyonpyon

simple さん、WinArrow さん、もこな2 さん 返答ありがとうございます。
 
説明不足でしたので、補足します。
 
シート1:表示
シート2:目次
シート3:データ(シート上部にソートや絞込みを行うためのオプションボタンを設けてあり、下段にその結果を表示します)
 
やりたいことは、上記をブック指定で印刷した時、表紙と目次はそのまま印刷し、
データシートを印刷する時に「ソートラジラジオボタン」がTureの場合は、改ページ毎にタイトルと下段のソート結果部分を印刷し
「絞り込みラジオボタン」がTureの時は改ページ毎のタイトルは印刷はしないで下段のソート結果部分のみを印刷するというものです。
ソースコードは以下です。
 
Private Sub Workbook_BeforePrint(Cancel As Boolean)
     
    Dim Wb As Workbook
    Dim Ws As Worksheet
    Dim DataLastRow As Object
    Dim strSheetName As String
     
    Set Wb = ThisWorkbook
    Set Ws = Wb.Worksheets("データ")
    Set DataLastRow = Ws.Cells(FirstTitleRow, PriorityCol)
 
    strSheetName = ActiveSheet.Name
     
    If strSheetName <> "表紙" And strSheetName <> "目次" Then
         
        If ActiveSheet.OLEObjects("ソートラジオボタン").Object.Value = True Then
            Application.PrintCommunication = False
            With ActiveSheet.PageSetup
                .PrintTitleRows = "$25:$25"
                .PrintTitleColumns = ""
            End With
            Application.PrintCommunication = True
        End If
         
        If ActiveSheet.OLEObjects("絞り込みラジオボタン").Object.Value = True Then
            Application.PrintCommunication = False
            With ActiveSheet.PageSetup
                .PrintTitleRows = ""
                .PrintTitleColumns = ""
            End With
            Application.PrintCommunication = True
        End If
             
        ActiveSheet.PageSetup.PrintArea = Ws.Range(Cells(FirstTitleRow, StartCol), _
                                            Cells(DataLastRow, MonneyCol + 1)).Address
     
    End If
     
    Set Wb = Nothing
    Set Ws = Nothing
    Set DataLastRow = Nothing
 
End Sub
 

回答
投稿日時: 17/12/17 10:19:41
投稿者: simple

コード提示ご苦労さまでした。
 
そのイベントプロシージャは、
・印刷命令が行わたとき、「一回だけ」動作するものです。
・各シート毎に実行されるものでもないですし、
・印刷そのものが、各シートを選択することを要件にしているわけでもありません。
 
ですから、Activesheetの名前で判断することが、いかに効果が無いことか、
おわかりいただけるでしょうか。
 
解決策は、皆さんが提示されているとおりでしょう。

回答
投稿日時: 17/12/18 13:18:05
投稿者: もこな2

回答というか気になる点を何点か。
  
私が不勉強なだけかもしれませんが、「FirstTitleRow」、「PriorityCol」、「StartCol」、「MonneyCol」というのは別途宣言された定数や変数でしょうか?(オブジェクトブラウザで検索してみましたがヒットせず。)それぞれが、定数や変数であって、かつ、番号、列番号である場合、「DataLastRow」という変数についてRangeオブジェクトが格納されるとおもうんですが期待通りの動きなんでしょうか?(「データ」シートの最終行の行番号が格納されてほしいような変数名だと思うんですが・・・)
  
次に、

strSheetName = ActiveSheet.Name
If strSheetName <> "表紙" And strSheetName <> "目次" Then
の部分ですが、アクティブシートの名前が「表紙」でないとき、かつ、アクティブシートの名前が「目次」でないときに処理をするということですから、素直にアクティブシートの名前が「データ」のときという表現のほうがよろしいように思えます。
ただ、全体の処理を見ると、アクティブシートがどうであるかに関わらず「データ」シートの操作をしたいように思えますので、そもそもIFで分岐させる必要がないと思われます。(というより、いまのままですと「表紙」「目次」がアクティブなときに印刷実行したら、コードが実行されなくなりませんか?)
  
  
以下は、趣味レベルの話になりますので、余力があるときに読んでみてください。
  
記述されている処理内容をみると、「ソートラジオボタン」、「絞り込みラジオボタン」は排他であるように推測します。
この場合、好みの問題ではありますが、Select Case による分岐で処理するという方法もあります。
With Worksheets("データ")
    Application.PrintCommunication = False
    Select Case True
        Case .OLEObjects("ソートラジオボタン").Object.Value = True
            With .PageSetup
                .PrintTitleRows = "$25:$25"
                .PrintTitleColumns = ""
            End With
         Case .OLEObjects("ソートラジオボタン").Object.Value = True
            With .PageSetup
                .PrintTitleRows = ""
                .PrintTitleColumns = ""
            End With
    End Select
    .PageSetup.PrintArea = _
        .Range(Cells(FirstTitleRow, StartCol), Cells(DataLastRow, MonneyCol + 1)).Address
End With

また、提示のあったコードは、Workbookの「BeforePrint」イベントに記述されています。このイベントは、ブック上のいずれのシート、範囲を印刷する場合でも発生します。(=「データ」シートの印刷以外でもイベントが発生します。)しかし、その内容は、「データ」シートに配置されたオブジェクトにより「データ」シートの「PageSetup」を行うものです。動くかどうかは別にして、一呼吸おいてからどのようなイベントを発動条件にすればよいか考えてみてください。
いろんな考え方があるので、絶対正解とは言いませんが、私なら↑のようなプロシージャを標準モジュールに置いて、それぞれのラジオボタンのクリックイベントでそのプロシージャを呼び出すようにします。
  
そのほか、
Dim Wb As Workbook
Dim Ws As Worksheet
Set Wb = ThisWorkbook
Set Ws = Wb.Worksheets("データ")
とされてますが、「wb」が出てくる箇所が、「Set Ws=〜」の部分しかないので、「Wb」は削って、「Set Ws = ThisWorkbook.Worksheets("データ")」だけでいいんじゃないかとおもいます。

回答
投稿日時: 17/12/18 13:44:49
投稿者: もこな2

ちょっと修正。
 
With Worksheets("データ")
    Application.PrintCommunication = False
    Select Case True
        Case .OLEObjects("ソートラジオボタン").Object.Value = True
            With .PageSetup
                .PrintTitleRows = "$25:$25"
                .PrintTitleColumns = ""
            End With
         Case .OLEObjects("ソートラジオボタン").Object.Value = True
            With .PageSetup
                .PrintTitleRows = ""
                .PrintTitleColumns = ""
            End With
    End Select
    .PageSetup.PrintArea = _
        .Range(Cells(FirstTitleRow, StartCol), Cells(DataLastRow, MonneyCol + 1)).Address
  Application.PrintCommunication = True
End With

回答
投稿日時: 17/12/18 19:05:56
投稿者: baoo

2つのラジオボタンで動作が変わるのはPrintTitleRowsだけのようですから、
私なら下記のようにします。

        Application.PrintCommunication = False
        With ActiveSheet.PageSetup
            If ActiveSheet.OLEObjects("ソートラジオボタン").Object.Value = True Then
                .PrintTitleRows = "$25:$25"
            Else
                .PrintTitleRows = ""
            End If
            .PrintTitleColumns = ""
        End With
        ActiveSheet.PageSetup.PrintArea = Ws.Range(Cells(FirstTitleRow, StartCol), _
                                            Cells(DataLastRow, MonneyCol + 1)).Address
        Application.PrintCommunication = True
ラジオボタンの値をあえてきちんとチェックするというのもアリだと思います。
私の場合、かつてはきちんとチェックしていたというか、
排他だから最後の値はチェックしなくても動作するということに気づいていませんでした。
その後、上司がチェックしていないのを見て以来マネしています。
 
ところで私はVBを初めて触って以来ラジオボタンではなく、オプションボックスと呼んでいますが、
この呼び名はかなり少数派ですね。
 

投稿日時: 17/12/18 23:04:56
投稿者: pyonpyon

WinArrowsさん、 もこな2さん、 細雪さん、回答ありがとうございます。
 
皆さんのコードの提示はありがたく拝見しました。いいとこどりで採用させていただきます。
 
さて、本来質問したかったのは「ブック印刷中に特定シートの印刷前のイベントは拾えるのか?」です。
(ワークブックのイベントプロシージャやワークシートののイベントプロシージャを調べたのですが、該当するようなイベントがわかりませんでした。)
やりたいことは、下記5)です。
 
1)このブックは不特定多数の人が使う。
2)「表紙シート」、「補足事項シート」はマクロや関数はなく、文書を記述しているのみ。
3)「ソート・絞込みシート」は上部にオプションボタン、チェックボックス等があり、ユーザはそれらを操作してソートや絞込みを行い、結果をシート下部に表示する。
4)ブック印刷する。(表紙、補足事項、ソート・絞込み結果の一式を印刷)
5)ブック印刷中に「ソート・絞込みシート」印刷前のイベントを拾って次の処理を行いたい。
  → ソートだった場合は改ページ時にタイトルを出力し、絞込みの場合は改ページ毎のタイトルは出力しない。
 
ご教示お願いします。

回答
投稿日時: 17/12/18 23:43:02
投稿者: simple

>「ブック印刷中に特定シートの印刷前のイベントは拾えるのか?」
質問の意図がわかりません。
 
オプションボタンなら、例えばそのクリック・イベントプロシージャのなかで
タイトル設定などの印刷設定をすれば済む話じゃないですか?
 
というのは、印刷設定はシート毎に保存されますから、
別に、ブックの印刷のBeforePrintなどというタイミングに
実行する必要はまったくないですよね。
前もって設定しておけば済む話です。
 
イベントの基本をよく学習してください。
 
# ところで、私の発言は理解されたんでしょうか。
# ActiveSheet依存はほどほどに。

回答
投稿日時: 17/12/19 07:12:32
投稿者: simple

追記します。
「ブック印刷中に特定シートの印刷前のイベントは拾えるのか」
とのこと。
まず、特定シートのBeforePrintイベントというものは用意されていません。
 
別方式を提案しましたが、
今の方針の延長線上でするなら、
すでに皆さんから提案があったように、
特定シートを名指しして、そのシートの印刷設定(タイトル行、印刷範囲指定等)を
実行させればよいだけではないですか?
 
Workbook_BeforePrintが動作するタイミングでたまたまアクティブであったシートに
依存するのが間違いなんです。そこはきちんと理解されたのですか?

回答
投稿日時: 17/12/19 11:39:36
投稿者: もこな2

引用:
4)ブック印刷する。(表紙、補足事項、ソート・絞込み結果の一式を印刷)
について、そもそもブック印刷っていうのが何かわからないです。(作業グループにして印刷させるんでしょうか?)
 
一言だけ言わせてもらえば、たとえば「表紙」だけ印刷したくても、「Workbook_BeforePrint」イベントに、「データ」シートの印刷設定を行う記述があればそこを通って必要ないシートの印刷設定を実行します。印刷設定程度であればたいした時間はかからないのでユーザーも気づかず文句も言わないでしょうが、本来どのタイミングで印刷設定をすべきかということは、開発を行う上で考えておいた方がよいように思います。
まぁ、昨日の回答の趣味レベル以降にも書きましたし、simpleさんも言ってくださっているので細かいところは割愛します。
 
以下、どうしても印刷実行時に「データ」シートの印刷設定をする方法を考えてみたところ2つほど思いつきましたので、追加回答します。
 
作戦1
Workbook_BeforePrintイベント時に、「データ」シートが印刷対象に含まれていたら(=選択されていたら)なんやかんやの処理をする。
Private Sub Workbook_BeforePrint(Cancel As Boolean)
Dim ws As Worksheet
For Each ws In ActiveWindow.SelectedSheets
    If ws.Name = "データ" Then
        'なんやかんやの処理
    End If
Next
End Sub

 
作戦2
印刷マクロを自分で作ってしまう。
Sub Sample2()
With ThisWorkbook
    .Worksheets("表紙").PrintOut
    .Worksheets("目次").PrintOut
    With .Worksheets("データ")
        'なんやかんやの処理
        .PrintOut
    End With
End With
End Sub

投稿日時: 17/12/20 00:03:00
投稿者: pyonpyon

simple さんへ
 
>オプションボタンなら、例えばそのクリック・イベントプロシージャのなかで
>タイトル設定などの印刷設定をすれば済む話じゃないですか?
  
>というのは、印刷設定はシート毎に保存されますから、
>別に、ブックの印刷のBeforePrintなどというタイミングに
>実行する必要はまったくないですよね。
>前もって設定しておけば済む話です。
→目から鱗です。印刷の都度設定しないと思い込んでいました。
→ご指摘通りに修正し、うまくいくことを確認できました。
→ありがとうございました。
  
>イベントの基本をよく学習してください。
→頑張ります。
  
># ところで、私の発言は理解されたんでしょうか。
># ActiveSheet依存はほどほどに。
→現在ActiveSheetは使用していません。ご指摘ありがとうございました。

投稿日時: 17/12/20 00:10:33
投稿者: pyonpyon

simpleさん、WinArrowさん、もこな2さん、baooさん
 
最近思い込みが強くなっていて、今回もそんな感じの落ちで申し訳ありませんでした。
 
未熟者に色々熱いご指導をしていただきただただ感謝しております。ありがとうございました。
また機会がありましたらよろしくお願いします。