[[20210602121705]] 『Set から、コード見直しについて』(しのみや) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『Set から、コード見直しについて』(しのみや)

Set から、コード見直しについて

 何度も教えて頂いております。
 『Setについて』http://www.excel.studio-kazu.jp/kw/20210526152051.html
 『Set変数設定の場所・コードの書き方など』http://www.excel.studio-kazu.jp/kw/20210527103025.html
 『ActiveWorkbookをSetする について』http://www.excel.studio-kazu.jp/kw/20210528111608.html
 今まで使っていたコードを直しているのですが、部分で質問させて頂いており
 質問がぼやけていたので、全体を書かせてもらいます。ただ長くなります…

 上記の質問で教えて頂いたことを理解して使わさせてもらっているのですが、
 新しいことばかりで頭がついていっておらず抜け落ちてしまっている個所もあるかもしれません…

 【シートの状況】
 Sheet1(日次)
 ラベル「Lbl管理表1」(管理表1.xlsxのパス)
 ラベル「Lbl一覧表2」(一覧表2.xlsxのパス)
 ラベル「Lbl一覧表3」(一覧表3.xlsxのパス)
 * 管理表1のデータファイルを元にSUMとVlookupをして一覧表2と一覧表3の表にしています
  管理表1を先に開いてから一覧表2と一覧表3を開かないと、
  「このブックには、ほかのデータソースへのリンクが含まれています」のメッセージが
  出ます

  ラベル「Lbl保存先Path」(保存先フォルダのパス)

  コマンドボタン「Cmd印刷」
  コマンドボタン「Cmdファイル保存」

 Sheet2(月次)
 コマンドボタン「Cmd印刷」

 【希望の動作】
 ●日次シートのCmd印刷を押す
 ↓
 管理表1と一覧表2と一覧表3を開く
 ↓
 ActiveWorkbookのパスと同じところに管理表1のファイルを値貼り付けをする(自店バックアップ用)
 ↓
 一覧表2と一覧表3を両面印刷する
 ↓
 メッセージボックスで管理表1の件数を出力
 ↓
 日次シートを選択

 ●日次シートのCmdファイル保存を押す
 ↓
 管理表1を開く
 ↓
 Lbl保存先Pathに管理表1のファイルを値貼り付けをする(他店参照用)

 ●月次シートのCmd印刷を押す
 ↓
 管理表1と一覧表2と一覧表3を開く
 ↓
 ActiveWorkbookのパスと同じところに管理表1のファイルを値貼り付けをする(自店バックアップ用)
 ↓
 一覧表2と一覧表3を両面印刷する
 ↓
 メッセージボックスで管理表1の件数を出力
 ↓
 月次シートを選択

 【VBEの画面】
 Sheet1(日次)
 Private Sub Cmd印刷_Click()
    Dim Str印刷日付 As String
    With Sheets(Me.Name)
        If .Range("F10") = "" Then
            Str印刷日付 = Day(.Range("F8")) & "日"
        Else
            Str印刷日付 = Day(.Range("F10")) & "日"
        End If
    End With
    Call Subファイル保存("Cmd印刷", Str印刷日付)
    Call Sub印刷(Str印刷日付)
    MsgBox "印刷しました"    ’★1
 End Sub

  Private Sub Cmdファイル保存_Click()
    Dim Str印刷日付 As String
    With Sheets(Me.Name)
        If .Range("F10") = "" Then
            Str印刷日付 = Day(.Range("F8")) & "日"
        Else
            Str印刷日付 = Day(.Range("F10")) & "日"
        End If
    End With
    Call Subファイル保存("Cmdファイル保存", Str印刷日付)
    MsgBox "ファイル保存しました。" ’★1
 End Sub

 Sheet2(月次)
 Private Sub Cmd印刷_Click()
    Dim Str印刷日付 As String
    With Sheets(Me.Name)
        If .Range("F23") = "" Then
            Str印刷日付 =  Day(.Range("F21")) & "日"
        Else
            Str印刷日付 =  Day(.Range("F23")) & "日"
        End If
    End With
    Call Subファイル保存("Cmd印刷", Str印刷日付)
    Call Sub印刷(Str印刷日付)
    MsgBox "印刷しました"
 End Sub

 Module1
 Public Sub Sub印刷(ByVal Str印刷日付 As String)
    Dim wb             As Workbook
    Dim ws             As Worksheet
    Dim wb管理表1      As Workbook
    Dim wb一覧表2      As Workbook
    Dim wb一覧表3      As Workbook
    Dim Lng最終行      As Long  '終了後メッセージに確認件数を表示するために取得

    Application.ScreenUpdating = False
    Set wb = ActiveWorkbook
    Set ws = ActiveSheet

    With Worksheets("日次")
        Set wb管理表1 = Workbooks.Open(.Lbl管理表1.Caption)
        Set wb一覧表2 = Workbooks.Open(.Lbl一覧表2.Caption)
        Set wb一覧表3 = Workbooks.Open(.Lbl一覧表3.Caption)
    End With
    Lng最終行 = wb管理表1.Worksheets("管理表").Cells(Rows.Count, "C").End(xlUp).Row

    '一覧表2と一覧表3を両面印刷する
    With wb
        wb一覧表2.Worksheets("最新").Copy before:=.Sheets(1)
        .Sheets("最新").Name = "一覧表2"
        wb一覧表2.Close False
        With .Sheets("一覧表2")
            .UsedRange.Value = .UsedRange.Value
            .Range("B1").Value = "一覧表2(" & Str印刷日付 & "現在)"
        End With

        wb一覧表3.Worksheets("最新").Copy before:=.Sheets(1)
        .Sheets("最新").Name = "一覧表3"
        wb一覧表3.Close False
        wb管理表1.Close False
        With .Sheets("一覧表3")
            .UsedRange.Value = .UsedRange.Value
            .Range("B1").Value = "一覧表3(" & Str印刷日付 & "現在)"
        End With

        .Activate
        .Sheets(Array("一覧表2", "一覧表3")).Select
        ActiveWindow.SelectedSheets.PrintOut
        Application.DisplayAlerts = False
        .Sheets(Array("一覧表2", "一覧表3")).Delete
        Application.DisplayAlerts = True
        .Worksheets(ws.Name).Select    '★2
    End With
    Application.ScreenUpdating = True

    MsgBox Lng最終行 & "件です。", vbInformation + vbOKOnly '★1
 End Sub

 Module2
 Public Sub Subファイル保存(ByVal Strボタン As String, ByVal Str印刷日付 As String)
    Dim wb                As Workbook
    Dim wb管理表1         As Workbook
    Dim wbCopy            As Workbook
    Dim BackUpName        As String

    Application.ScreenUpdating = False
    Set wb = ActiveWorkbook
    Set wb管理表1 = Workbooks.Open(Worksheets("日次").Lbl管理表1.Caption)
    BackUpName = "01 管理表" & "(" & Str印刷日付 & ")"

    wb管理表1.Worksheets("管理表").Copy
    Set wbCopy = ActiveWorkbook   ’自分で理解できるよう、ActiveWorkbookにしています
    wb管理表1.Close False

    With wbCopy.Worksheets(1)
        .UsedRange.Value = .UsedRange.Value
        .Shapes("Cmd送付用").Delete
        .Range("A1").Select
        With ActiveWindow   ’ウィンドウ枠の固定がされているので、この設定にしています
            .ScrollRow = 2
            .ScrollColumn = 2
        End With
        Select Case Strボタン
            Case "Cmd印刷"
                .SaveAs Filename:=wb.Path & "\" & BackUpName & ".xlsx", FileFormat:=xlOpenXMLWorkbook
            Case "Cmdファイル保存"
                .SaveAs Filename:=wb.Worksheets("日次").Lbl保存先Path & "\" & BackUpName & ".xlsx", FileFormat:=xlOpenXMLWorkbook
        End Select
    End With

    wbCopy.Close False
    Application.ScreenUpdating = True
 End Sub

 【特に教えて頂きたいこと】
 ★1 Cmd印刷の動作後のMsgboxが「○件です」と「印刷しました」の表示が2回出ています。
   「○件です。印刷しました。」と1回のメッセージにしたいのですが、
   Private Sub Cmdファイル保存_Click()のMsgboxの記述の位置と同じようにしたほうが統一性があってよいかなと思っております…。
   Lng最終行をどのようにPrivate Sub Cmd印刷_Click()に持ってくるのが良いのでしょうか

 ★2 シート名の指定の仕方はおかしくないですか?

 過去に質問させていただいてさまざまなご回答をいただき、
 たくさん調べることがあって読み落としてしまっている部分がありそうで…心配です。
 今までマクロの記録でなんとかしていたのですが、後から見づらいのでしっかり見直したいと思っています。
 自分で見やすく書くならこのようにする等…一部だけでも大丈夫です。 
 ご面倒かけますが教えて頂ければ助かります。   

< 使用 Excel:Excel2010、使用 OS:Windows10 >


1だけですが
Sub印刷が終わったら処理を終わるみたいなのでSub印刷の最後のMsgboxにつなげて書いたらいいんじゃないかな
あくまで印刷するコードを実行してるのはSub印刷ですし
ボタンを増やすたびにイベントの最後に「msgbox"印刷しました"」を記入するのは手間じゃないですか
(砂糖) 2021/06/02(水) 12:48

ThisWorkbookってご存知ですか?
ActiveWorkbookって、↑に当たりませんか?
Active〜は、不定なので、マクロ実行時の状態で、
どのオブジェクトか分からないんですよ。

(tkit) 2021/06/02(水) 14:10


 長い質問ながらご回答ありがとうございます

 砂糖さん ありがとうございます

 Sub印刷の最後に置くとすると、
 Subファイル保存も同じ位置にMsgboxを置いたほうが後から読みやすいかなと思っておりまして…
 他のコードを作るときも統一感があったほうがよいと思いますし…
 ボタンを増やすたびにMsgboxも良くなさそうですし…

 でもそうすると、
 Cmd印刷から入ったSubファイル保存のときもメッセージが出るので、
 Subファイル保存から抜け出てから書くしかないのかな、と思って質問のコードになっています。
 良い方法が見つからなくて、どうしたものかなと…

 tkitさん ありがとうございます

 ActiveWorkbookをやめてThisWorkbookに変更します。
(しのみや) 2021/06/02(水) 14:16

 tkitさんに頂いた ThisWorkbookについて調べてみました

 1
 Set wb = ActiveWorkbook のところを
 Set wb = ThisWorkbook にしました。

 そうすると、
 Set ws = ActiveSheet これは?と思って調べたのですが
 Set ws = thisSheet のようなものがなく

 (そもそも、今回のコードであれば
  dim ws as string
  ws = wb.name でもよいように思ってきたのですが…)

 みなさんは、
 Set wb = ThisWorkbook
 Set ws = ActiveSheet このように指定されているのでしょうか?

 2
 コピーで作成された直後のファイルも
 極力Activeは使わないほうがよいのかなと思うようになってきまして…
 wb管理表1.Worksheets("管理表").Copy
 Set wbCopy = ActiveWorkbook
 ↓
 Set wbCopy = Workbooks(Workbooks.Count)にさせてもらおうかなと思っています。
(しのみや) 2021/06/02(水) 15:30

 (そもそも、今回のコードであれば
  dim ws as string
  ws = wb.name でもよいように思ってきたのですが…)
 これではだめでしたね…間違えました。
(しのみや) 2021/06/02(水) 16:17

コードは、思った通り動作すれば、どんな記述でも
「間違い」ではないと思っています。

問題は可読性だと思っています。
数か月前、数週間前に書いたコードは他人が書いたように
見えてしまうのです。

当然、読み解くのに時間が掛かりますので、
何をしているか一目見て分かるように、記述することを
おススメします。

まずはご自身の記述ルールを作るほうが悩まないのでは。

私なりに書き直してみました。
コンパイルチェックのみです。
参考にどうぞ。

 'Sheet1
 Private Sub Cmd印刷_Click()
    Dim Str印刷日付 As String
    Str印刷日付 = Func印刷日付取得(Me)
    Subファイル保存 Str印刷日付, Clk_Cmd印刷, False
    Sub印刷 Str印刷日付, Me, True
 End Sub
 Private Sub Cmdファイル保存_Click()
    Dim Str印刷日付 As String
    Str印刷日付 = Func印刷日付取得(Me)
    Subファイル保存 Str印刷日付, Clk_Cmdファイル保存, True
 End Sub

 'Sheet2
 Private Sub Cmd印刷_Click()
    Dim Str印刷日付 As String
    Str印刷日付 = Func印刷日付取得(Me)
    Subファイル保存 Str印刷日付, Clk_Cmd印刷, False
    Sub印刷 Str印刷日付, Me, True
 End Sub

 'Module1
 Public Enum ClickButtons
 Clk_Cmd印刷 = 1
 Clk_Cmdファイル保存
 End Enum
 Private Enum PathType
 Op管理表1 = 1
 Op一覧表2
 Op一覧表3
 Sa保存先
 End Enum

 Public Sub Sub印刷(ByVal Str印刷日付 As String, _
 ByVal wsボタン押下シート As Worksheet, _
 ByVal bln印刷Msg表示 As Boolean)
    Dim Lng最終行      As Long  '終了後メッセージに確認件数を表示するために取得
    Application.ScreenUpdating = False

    Lng最終行 = Func管理表の最終行取得()
    '一覧表2と一覧表3を両面印刷する

    最新シートの取得 Str印刷日付, Op一覧表2
    最新シートの取得 Str印刷日付, Op一覧表3
    Dim arrシート名群() As Variant
    arrシート名群 = Array("一覧表2", "一覧表3")
    With ThisWorkbook.Worksheets(arrシート名群)
        .PrintOut
        .Delete
    End With
    ThisWorkbook.Activate
    wsボタン押下シート.Select

    Application.ScreenUpdating = True
    If bln印刷Msg表示 Then MsgBox Lng最終行 & "件です。印刷しました。", vbInformation + vbOKOnly
 End Sub

 Public Function Func印刷日付取得(ByVal ws As Worksheet) As String
    Dim buf As String
    With ws
        Select Case .Name
        Case "日次"
            If .Range("F10") = "" Then
                buf = Format(.Range("F8").Value, "d日")
            Else
                buf = Format(.Range("F10").Value, "d日")
            End If
        Case "月次"
            If .Range("F21") = "" Then
                buf = Format(.Range("F23").Value, "d日")
            Else
                buf = Format(.Range("F21").Value, "d日")
            End If
        End Select
    End With
    Func印刷日付取得 = buf
 End Function

 Private Function Func各パス取得(ByVal target As PathType) As String
    Dim buf As String
    With ThisWorkbook.Worksheets("日次")
        Select Case target
        Case Op管理表1: buf = .Lbl管理表1.Caption
        Case Op一覧表2: buf = .Lbl一覧表2.Caption
        Case Op一覧表3: buf = .Lbl一覧表3.Caption
        Case Sa保存先:  buf = .Lbl保存先Path.Caption
        End Select
    End With
    Func各パス取得 = buf
 End Function

 Private Function Func管理表の最終行取得() As Long
    Dim wb As Workbook
    Set wb = Workbooks.Open(Filename:=Func各パス取得(Op管理表1), ReadOnly:=True)
    Dim n As Long
    n = wb.Worksheets("管理表").Cells(Rows.Count, "C").End(xlUp).Row
    wb.Close False
    Func管理表の最終行取得 = n
 End Function

 Private Sub 最新シートの取得(ByVal Str印刷日付 As String, ByVal target As PathType)
    Dim Strシート名 As String
    Select Case target
    Case Op管理表1: Exit Sub
    Case Op一覧表2: Strシート名 = "一覧表2"
    Case Op一覧表3: Strシート名 = "一覧表3"
    Case Sa保存先:  Exit Sub
    End Select

    If target = Op管理表1 Then Exit Sub
    Dim wb As Workbook
    Set wb = Workbooks.Open(Filename:=Func各パス取得(target), ReadOnly:=True)
    wb.Worksheets("最新").Copy before:=ThisWorkbook.Worksheets(1)
    wb.Close False
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Worksheets("最新")
    With ws
        .Name = Strシート名
        .UsedRange.Value = .UsedRange.Value
        .Range("B1").Value = Strシート名 & "(" & Str印刷日付 & "現在)"
    End With
 End Sub

 Public Sub Subファイル保存(ByVal Str印刷日付 As String, _
                           ByVal Clkボタン As ClickButtons, _
                           ByVal bln保存Msg表示 As Boolean)
    Dim wb管理表1         As Workbook
    Dim wbCopy            As Workbook
    Dim BackUpName        As String
    Application.ScreenUpdating = False

    Set wb管理表1 = Workbooks.Open(Func各パス取得(Op管理表1), ReadOnly:=True)
    BackUpName = "01 管理表" & "(" & Str印刷日付 & ")"
    wb管理表1.Worksheets("管理表").Copy
    Set wbCopy = ActiveWorkbook      '自分で理解できるよう、ActiveWorkbookにしています
    wb管理表1.Close False

    With wbCopy.Worksheets(1)
        .UsedRange.Value = .UsedRange.Value
        .Shapes("Cmd送付用").Delete
        .Range("A1").Select
    End With
    With ActiveWindow      'ウィンドウ枠の固定がされているので、この設定にしています
        .ScrollRow = 2
        .ScrollColumn = 2
    End With
    wbCopy.SaveAs Filename:=Funcバックアップ保存パス取得(BackUpName, Clkボタン), _
                  FileFormat:=xlOpenXMLWorkbook
    wbCopy.Close False

    Application.ScreenUpdating = True
    If bln保存Msg表示 Then MsgBox "ファイル保存しました。", vbInformation
 End Sub

 Private Function Funcバックアップ保存パス取得(ByVal BackUpName As String, _
                                              ByVal Clkボタン As ClickButtons) As String
    Dim buf As String
    Select Case Clkボタン
    Case Clk_Cmd印刷:         buf = ThisWorkbook.Path & "\" & BackUpName & ".xlsx"
    Case Clk_Cmdファイル保存: buf = Func各パス取得(Sa保存先) & "\" & BackUpName & ".xlsx"
    End Select
    Funcバックアップ保存パス取得 = buf
 End Function

(tkit) 2021/06/02(水) 17:12


これだけやって意味が解らない、使い方が解らないのなら
Set など使わなきゃいいのに・・・。
と、私は思います!
(hehe) 2021/06/02(水) 18:09

同感です。
(かん) 2021/06/02(水) 19:13

 既に改善案が提示されていますので是非研究されたらよいと思いますが、
 現行の質問者さんのコードに沿って、若干のコメントをします。

 1. Sheetモジュールでは、シートの指定をしていないセル範囲は、
    記述されたシートそのものが指定されたものとされます。
  (以前のスレッドを読み返してみて下さい。明確に指摘がありました)

    ですから、Sheet1(日次)モジュールの
    With Sheets(Me.Name)
         If .Range("F10") = "" Then
    などは、単に、     
    If Range("F10") = "" Then  で問題ありません。

    なお、書くとしても、
       With Sheets(Me.Name)ではなく
       With Me
    でしょう。("どんだけ名前が好きなの"症候群wwですよ。)   

 2. .Worksheets(ws.Name).Select    '★2
    もそうですね。ws.Selectです。

 3.(既に指摘された話です)
    プロシージャの冒頭で使うActiveWorkbookは、それだとコンテキストが不明なので、
    この場合はThisWorkbookとするのがよいと思います。
    そのコードが書かれているブックの意味であり、明確です。

    ワークシートをコピーした直後にできた新しいブックの指定は、
    ActiveWorkbookで悪いことはないと思います。
    .Countを使わないといけないことは無いと思います。
    ActiveWorkbookの実態が何かは明確だからです。

 4. 一般論ですが、プロシージャの名前と中身がかけ離れていると理解しにくくなります。
   もう少し、内容に応じた分け方にしたほうがよいかな、という印象です。
   "印刷"といいながら、ブックやシートを作成する機能が混在している点が代表でしょうか。

(γ) 2021/06/02(水) 22:00


 tkitさん γさん ありがとうございます
 コード、コメント共に助かります。
 そもそものお話や、抜け落ちているところがたくさんありますね…
 今から勉強させてもらいます。

 heheさん かんさん
 そんな中お教え下さる方に感謝しています。

(しのみや) 2021/06/03(木) 09:35


 tkitさん 頂いたコードの動きを勉強させてもらいました。

 そこ?っていう質問になるかもしれないのですが…

 1
 Enumの列挙型変数を知りました。
 変数名のつけ方のお話になると思うのですが…
 Clk こちらはクリックするボタンかなと思います。
 そうするとOpとSaはどういう指定になるのかなと…

 2
 Sub印刷 Str印刷日付, Me, True
 こちらで、Meの引数を渡して
 ByVal wsボタン押下シート As Worksheetで受け取っていますが

 今までの私ですとMe.nameを渡して、
 ByVal wsボタン押下シート As Stringにしておりました。

 Worksheetを渡しているのは、
 今回のコードは単純なので使っていないだけで
 Sub印刷の中でシート名以外の情報も取る場合があるかもしれないのを想定して
 Worksheetで渡のかなと…
 「シートに関する情報を受け取ったとわかりやすい」というメリットがある…
 こんな考えで大丈夫でしょうか…

 γさん ありがとうございます
 
 2.
  with wb
   .ws.Select
  End with
  にしていてエラーになっておかしいなぁと思っていました…

 ご丁寧に回答くださるおかげで、
 初めてSetを知ったときから比べて少しは理解できてきたと思います… ^^;
 読み返して勉強させてもらっております。

(しのみや) 2021/06/03(木) 14:45


いろいろ学ばれているようですね。
私も独学で覚えたので、最初は苦労しました。

>1.そうするとOpとSaはどういう指定になるのかなと…

適当にOpen、Saveの頭2文字を取っただけで、大きな意味はありません。
Enum(列挙型)を使っている意味は、選択の範囲を固定するためです。
試しに、VBEのModule1でFunc各パス取得を記述してみてください。
インテリセンスが働いて、PathType の要素が選択肢として表示されます。
大規模なマクロを組もうとすると、バグを減らせる非常に有効なテクニックだと思い、
よく使っています。

こちらを参考にどうぞ。
https://reime.hatenadiary.jp/entry/2019/09/16/235554

>2.「シートに関する情報を受け取ったとわかりやすい」というメリットがある…

コード上、シートのメソッドを実行するので、シートそのもの(Worksheetオブジェクト)を
引数として渡しています。「wsボタン押下シート.Select」

シート名を渡してもいいですが、面倒じゃないですか?
Worksheets(シート名)をいちいち記述しなきゃいけませんよね?
プロシージャで欲しているのは、シートそのものなので、そのままシートを渡せばいいんです。

基本ですが、オブジェクトは明確に指定すべきです。
オブジェクト変数を使用すれば、オブジェクトは固定されます。

↓にサンプル用意しましたので、新しいブックの標準モジュールに貼り付けて、
ステップ実行してみてください。

 Sub sample1()
     Worksheets("Sheet1").Name = "aaa"
     Worksheets("Sheet1").Name = "bbb"
 '    Worksheets("aaa").Name = "bbb"
 End Sub

 Sub sample2()
     Dim ws As Worksheet
     Set ws = Worksheets("Sheet1")
     ws.Name = "aaa"
     ws.Name = "bbb"
 End Sub

sample1はエラーになります。
コード書く時、コピペでミスしそうじゃないですか?

(tkit) 2021/06/03(木) 15:54


 tkitさん ありがとうございます。
 Open、Saveの頭文字でしたか。なるほどイメージしやすいです。

 Enumでラベルを設定・パス取得するのは、少々混乱しました…
 選択肢が多くある場合には使えるようにしていきたいと思います。

 sampleありがとうございました。
 オブジェクトで判断できるので、「シート名」が必要なわけではないですね。
 (↑を何度も教えてもらっていることかと思いますが…)
 必要なもの=シート名しか送らないほうが良いような気がしていたので、
 頭が停止していました。
 固定で送ってしまってると、後々指定するときや変更するときにややこしくなりますね。

 tkitさん γさんに 教えていただいたことからコードを見直して…
 印刷する前にバックアップを取っておきたかったので、
 印刷ボタンにファイル保存と印刷の動作が入っております。
 わかりづらいのでコマンドボタンのオブジェクト名を「Cmdファイル保存と印刷」としてみました。
 それでもわかりづらいなと思っています…

 >"印刷"といいながら、ブックやシートを作成する機能が混在している点が代表でしょうか。
 別々のファイルのシート2枚を両面印刷をしようとしていて、
 両面にするにはシート選択をして印刷をする方法しか見つからなかったので…わかりづらいですね…

 もしよろしければ、
 お時間あるときに教えていただけると助かります。

 【シートの状況で変えたところ】
 Sheet1(日次)
  コマンドボタン「Cmd印刷」  → 「Cmdファイル保存と印刷」

 Sheet2(月次)
  コマンドボタン「Cmd印刷」  → 「Cmdファイル保存と印刷」

 Sheet1
 Private Sub Cmdファイル保存と印刷_Click()
    Dim Str印刷日付 As String
    Str印刷日付 = Fn印刷日付取得(Me)
    Call Subファイル保存("印刷", Str印刷日付)
    Call Sub印刷(Me, Str印刷日付)
 End Sub

 Private Sub Cmdファイル保存_Click()
    Dim Str印刷日付 As String
    Str印刷日付 = Fn印刷日付取得(Me)
    Call Subファイル保存("保存", Str印刷日付)
 End Sub

 Sheet2
 Private Sub Cmdファイル保存と印刷_Click()
    Dim Str印刷日付 As String
    Str印刷日付 = Fn印刷日付取得(Me)
    Call Subファイル保存("印刷", Str印刷日付)
    Call Sub印刷(Me, Str印刷日付)
 End Sub

 Module1
 Public Sub Subファイル保存(ByVal Strボタン As String, ByVal Str印刷日付 As String)
    Dim wb管理表 As Workbook
    Dim window   As window
    Dim wbCopy   As Workbook    
    Dim bakName  As String
    Dim bakPass  As String

    Application.ScreenUpdating = False        
    Set wb管理表 = Workbooks.Open(Worksheets("日次").Lbl管理表1.Caption)        
    bakName = "01 管理表" & "(" & Str印刷日付 & ").xlsx"
    Select Case Strボタン    
        Case "印刷"
            bakPass = ThisWorkbook.Path & "\bak\" & bakName            
        Case "保存"
            bakPass = ThisWorkbook.Worksheets("日次").Lbl保存先Path & "\" & bakName            
    End Select

    'バックアップファイル用に値貼り付けする
    wb管理表.Worksheets("管理表").Copy
    wb管理表.Close False
    Set window = ActiveWindow
    Set wbCopy = ActiveWorkbook

    With window
        .ScrollRow = 2
        .ScrollColumn = 2
    End With    
    With wbCopy.Worksheets(1)        
        .UsedRange.Value = .UsedRange.Value       
        .Shapes("Cmd送付用").Delete       
        .Range("A1").Select

        Application.DisplayAlerts = False
        .SaveAs Filename:=bakPass, FileFormat:=xlOpenXMLWorkbook
        Application.DisplayAlerts = True        
    End With

    wbCopy.Close False            
    If Strボタン = "保存" Then    
        MsgBox "保存しました。"        
    End If       
 End Sub

 Public Sub Sub印刷(ByVal wsボタン押下シート As Worksheet, ByVal Str印刷日付 As String)        
    Dim wb管理表1   As Workbook
    Dim wb一覧表2   As Workbook
    Dim wb一覧表3   As Workbook    
    Dim Lng最終行   As Long  '終了後メッセージに確認件数を表示するために取得

    Application.ScreenUpdating = False           
    With Worksheets("日次")    
        Set wb管理表1 = Workbooks.Open(.Lbl管理表1.Caption)
        Set wb一覧表2 = Workbooks.Open(.Lbl一覧表2.Caption)
        Set wb一覧表3 = Workbooks.Open(.Lbl一覧表3.Caption)        
    End With

    Lng最終行 = wb管理表1.Worksheets("管理表").Cells(Rows.Count, "C").End(xlUp).Row            
    '両面印刷する
    With ThisWorkbook
        wb一覧表2.Worksheets("最新").Copy before:=.Sheets(1)
        wb一覧表2.Close False

        .Sheets("最新").Name = "一覧表2"
        With .Sheets("一覧表2")            
            .UsedRange.Value = .UsedRange.Value            
            .Range("B1").Value = "管理表(" & Str印刷日付 & "現在)"            
        End With

        wb一覧表3.Worksheets("最新").Copy before:=.Sheets(1)
        wb一覧表3.Close False
        wb管理表1.Close False

        .Sheets("最新").Name = "一覧表3"        
        With .Sheets("一覧表3")            
            .UsedRange.Value = .UsedRange.Value            
            .Range("B1").Value = "管理表(" & Str印刷日付 & "現在)"        
        End With

        With .Worksheets(Array("一覧表2", "一覧表3"))
            .PrintOut
            Application.DisplayAlerts = False
            .Delete
            Application.DisplayAlerts = True
        End With                             
    End With

    wsボタン押下シート.Select           
    Application.ScreenUpdating = True       
    MsgBox "印刷しました。" & Lng最終行 & "件です。", vbInformation + vbOKOnly

 End Sub

 Function Fn印刷日付取得(ByVal ws As Worksheet) As String   
    Dim buf As String    
    With ws    
        Select Case .Name        
            Case "日次"            
                If .Range("F10") = "" Then
                    buf = Format(.Range("F8").Value, "yyyy年mm月dd日")
                Else
                    buf = Format(.Range("F10").Value, "yyyy年mm月dd日")
                End If               
            Case "月末処理"               
                If .Range("F22") = "" Then
                    buf = Format(.Range("F20").Value, "yyyy年mm月dd日")
                Else
                    buf = Format(.Range("F22").Value, "yyyy年mm月dd日")
                End If               
        End Select

    End With        
    Fn印刷日付取得 = buf    
 End Function
(しのみや) 2021/06/04(金) 15:25

 passはpathです…
(しのみや) 2021/06/04(金) 15:37

現状、思った通りに動作していれば、いいのではないでしょうか。

私個人の考えは、
いいコードは、簡潔かつ可読性が高いコードだと思っています。
可読性を上げるために、多少コード量が増えても、1つの括りを別のプロシージャにします。
なぜなら、プロシージャ名を好きなように命名できるからです。
そうすれば、別プロシージャのコードを見なくても、何をやっているかのイメージはできます。
ですので、メインのプロシージャがあり、目次のようなプロシージャが並び、
各々でプロシージャを呼び出すような形を念頭に置いて、コードを組んでいます。
また、共通性の持った同じコードを繰り返し記述するのを避けます。

そこで重要なのが、引数となります。
渡す引数で、渡したプロシージャで何をしているのかイメージできるように
気を付けます。
値でいいのか、オブジェクトがいいのか、考えながら。

ちなみに引数で使っていたEnum型はフラグとして使っています。
中身はただの数値です。

長々と失礼しました。

もう少し規模が大きいマクロを組もうとすると、オブジェクト変数、引数、冗長性の排除等を
理解して臨まないと、苦戦すると思います。

1つ1つ自身で試しながらがんばってください。
(tkit) 2021/06/04(金) 17:04


 ありがとうございます。
 教えて頂いて即再現できるようにはなりませんが…
 今からたくさんのコードを見直して理解していけたらと思います。
 また質問させて頂くことがあるかと思いますが、
 お時間ありましたら書き込んでいただけると助かります。
(しのみや) 2021/06/07(月) 10:51

コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.