[[20130513021038]] 『マクロで二つの元ブックから様式ブックへの転記』(usamiyu) ページの最後に飛ぶ

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

 

『マクロで二つの元ブックから様式ブックへの転記』(usamiyu)

 いつも大変お世話になっております。長文失礼します。また、ご相談させてください。

 様式ブック並びに転記元ブックm及び転記元ブックgが同一フォルダにあります。
これらとは別にマクロを記載したブックを作り、以下の手順で転記したいと考えました。
書いたコードは下記のとおりですが、For each構文でループするつもりが、情けないことに同じ箇所に
上書きされてしまいます。
どなたかどうかお知恵をお貸しいただけないでしょうか。

 【手順】
 1 様式ブックを開く
 2 転記元ブックm(csvファイル)を開く
 3 転記元ブックg(csvファイル)を開く
 4 サブルーチンで集計機能を使い、mを加工、gを加工
 5 様式ブックのC、F列の該当行に値(前月)が入っていたら、D、G列の値(当期)を上書きする
 6 D、G列の該当行をクリアする
 7 転記元ブックmのシートshfrommの各行のOutlineLevelが2だったら、様式ブックのD12〜D16の各セルに、 
  shfrommの各行のAB列の値を代入する  (←ココがD12に上書きされて失敗中です。)
 8 同じく、様式ブックのG12〜G16の各セルに、shfrommの各行のAE列の値を代入する
 9 7,8と同じことを転記元ブックgの条件で行う
 10 転記元ブックmをxl形式で保存して閉じる
 11 転記元ブックgをxl形式で保存して閉じる
 12  様式ブックを同じフォルダにA1セルの名前で保存、印刷して閉じる

 【レイアウト】
 (様式ブック)
       [A]                                     [B]    [C]     [D]     [E]     [F]  [G]  [H]           
 [1]  平成25年度 報告書(    4月末現在)                                                        
 [2]                                                                                                 
 [3]                                                                                   (単位: 円)
 [4]                                                                                                 
 [5]  項目                                    種別   仮                       支出                      
 [6]                                                 前月    当期     計      前月 当期   計            
 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜中略〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
 [12] M                                       j                            0                        0
 [13]                                         t             200         200                        0
 [14]                                         i      100     300         400                        0
 [15]                                         k                            0                        0
 [16]                                         g             100         100                        0
 [17] M計                                            100     600         700    0    0              0
 [18] G                                       j                            0                        0
 [19]                                         t             400         400                        0
 [20]                                         i       80      50         130                        0
 [21]                                         k                            0                        0
 [22] G計                                             80     450         530    0    0              0

 (転記元ブックm)※上記手順4にて加工後の姿(転記元ブックgも同様のレイアウト)
       [S]       [T]    [U] [V]    [W]  [X]  〜〜 略 〜〜  [Z] [AA] [AB] [AC] [AD] [AE] [AF]
 [1]  種別      取引年 月  取引日 番号 摘要                 YY  KK   SS   **   ※   FF   TT  
 [2]  t                 5           1 ○○                 0  100    0    0    0    0    0
 [3]  t                 5           1 ○○                 0    0  100    0    0    0    0
 [4]  t                 5           1 ○○                 0    0    0    0    0  100    5
 [5]  t   集計                                                     100            100     
 [6]  i                  5           3 △△                 0  200    0    0    0    0    0
 [7]  i                  5           3 △△                 0    0  200    0    0    0    0
 [8]  i                  5           3 △△                 0  -10  -10    0    0    0    0
 [9]  i   集計                                                190              0     
 [10] k                  5           8 ××                 0  300    0    0    0    0    0
 [11] k                  5           8 ××                 0    0  300    0    0    0    0
 [12] k                  5           8 ××                 0    0    0    0    0  300   15
 [13] k   集計                                                      300            300     
 [14] g                  5          15 ◎◎                 0  400    0    0    0    0    0
 [15] g                  5          15 ◎◎                0    0  400    0    0    0    0
 [16] g                  5          15 ◎◎                 0  -20  -20    0    0    0    0
 [17] g   集計                                                 380              0     
 [18] 総計                                                       970            400     

 【コード】
(長くなるので、サブルーチンShikkouseiriListは割愛しています。)
 Sub Make_Report()
    Dim wbt As Workbook   '様式ブック
    Dim wbm As Workbook     '転記元ブックm
    Dim wbg As Workbook      '転記元ブックg
    Dim shfromm As Worksheet
    Dim shfromg As Worksheet
    Dim shtod As Worksheet      '転記先シート
    Dim Filepathm As Variant
    Dim Filepathg As Variant
    Dim FilePatht As Variant
    Dim r As Range              '様式ブックの前月欄の範囲
    Dim c As Range
    Dim rm1 As Range            '様式ブックの項目Mの「仮」の当期の範囲
    Dim rm2 As Range            '様式ブックの項目Mの「支出」の当期の範囲
    Dim cm1 As Range
    Dim cm2 As Range
    Dim rg1 As Range            '様式ブックの項目Gの「仮」の当期の範囲
    Dim rg2 As Range            '様式ブックの項目Gの「支出」の当期の範囲
    Dim cg1 As Range
    Dim cg2 As Range
    Dim myRow As Range
    Dim sep As String

    sep = Application.PathSeparator '\

    '調査票様式を選択
    FilePatht = Application.GetOpenFilename("Excelファイル,*.xls*", , "様式ファイルを開く")
    If FilePatht = False Then Exit Sub
    '調査票様式ファイルを開く
    Set wbt = Workbooks.Open(FilePatht)
    Set shtod = wbt.Sheets(1)

    '転記元ブックm選択
    Filepathm = Application.GetOpenFilename("csvファイル,*.csv", , "mを開く")
    If Filepathm = False Then Exit Sub
    '転記元ブックmを開く
    Set wbm = Workbooks.Open(Filepathm)
    Set shfromm = wbm.Sheets(1)

    '転記元ブックg選択
    Filepathg = Application.GetOpenFilename("csvファイル,*.csv", , "gを開く")
    If Filepathg = False Then Exit Sub
    '転記元ブックgを開く
    Set wbg = Workbooks.Open(Filepathg)
    Set shfromg = wbg.Sheets(1)

    Application.ScreenUpdating = False  '画面描画停止

    MsgBox "題名に今月を入力しましたか?"    'vbOKonlyにしておいて、忘れていたら入力する?Exitはしたくない

    '--------------------------------------------------------
    '転記元csvファイルを加工したものを子プロシージャから呼ぶ
    '--------------------------------------------------------
    Call ShikkouseiriList(shfromm)
    Call ShikkouseiriList(shfromg)

    '--------------------------------------------------------
    '様式ブック(転記先シート)への転記処理
    '--------------------------------------------------------
    With shtod
        Set r = .Range("C12:C16,C18:C21,F12:F16,F18:F21")  '前月欄

            For Each c In r
                If Len(c.Value) >= 1 Then c.Value = c.Offset(, 1).Value    '前月欄が記載してあれば、当期欄の値を前月欄に移す
            Next

            r.Offset(, 1).ClearContents    '当期欄をクリア

        Set rm1 = .Range("D12:D16")   '項目Mの「仮」の当期欄
        Set rm2 = .Range("G12:G16")   '項目Mの「支出」の当期欄

            For Each cm1 In rm1
                 For Each myRow In shfromm.Range("A1").CurrentRegion.Rows
                    If myRow.OutlineLevel = 2 Then
                        cm1.Value = myRow.EntireRow.Range("AB1").Value  '<-------ここでcm1がループせず上書になってしまう。
                    End If
                 Next
            Next
            For Each cm2 In rm2
                For Each myRow In shfromm.Range("A1").CurrentRegion.Rows
                    If myRow.OutlineLevel = 2 Then
                       cm2.Value = myRow.EntireRow.Range("AE1").Value
                   End If
                 Next
            Next

         Set rg1 = .Range("D18:D21")   '項目Gの「仮」の当期欄
         Set rg2 = .Range("G18:G21")   '項目Gの「支出」の当期欄
            For Each cg1 In rg1
                For Each myRow In shfromg.Range("A1").CurrentRegion.Rows
                    If myRow.OutlineLevel = 2 Then
                         cg1.Value = myRow.EntireRow.Range("AB1").Value
                     End If
                Next
            Next
            For Each cg2 In rg2
                For Each myRow In shfromg.Range("A1").CurrentRegion.Rows
                    If myRow.OutlineLevel = 2 Then
                         cg2.Value = myRow.EntireRow.Range("AE1").Value
                     End If
                Next
            Next

    End With

    MsgBox "転記終了"

  '--------------------------------------------------------
  '転記元、転記先ブックを保存する
  '--------------------------------------------------------

    '転記元ブックm保存
    wbm.SaveAs Filepathm & sep & Left(shfromm.Range("A2"), 6) & shfromm.Range("Q2") & ".xls", FileFormat:=xlNormal
    wbm.Close False
     '転記元ブックg保存
    wbg.SaveAs Filepathg & sep & Left(shfromg.Range("A2"), 6) & shfromg.Range("Q2") & ".xls", FileFormat:=xlNormal
    wbg.Close False

    Application.ScreenUpdating = True  '画面描画再開

    '様式ブックを同じフォルダにA1セルの名前で保存
    With wbt
        .SaveAs FilePatht & sep & Sheets(1).Range("A1") & ".xls"
        .Sheets(1).PrintPreview
        .Sheets(1).PrintOut
        .Close
    End With 
End Sub


 やりたかったことは、rm1内の各セル に、shfrommの行の中のOutlineLevelが2のものの AB列の値を 順番に書き込みたいということかな?
 同じような構造のところが他にもあって、そこはうまくいっているということであれば、ちょっと悩んでしまうんだけど?

 確かに【長文】なので、usamiyuさんも回答者さん達も、なんだかわかりにくくなってしまいがちだけど、もし、やりたかったことが
 このとおりなら、コードとしては 

            For Each cm1 In rm1
                 For Each myRow In shfromm.Range("A1").CurrentRegion.Rows
                    If myRow.OutlineLevel = 2 Then
                        cm1.Value = myRow.EntireRow.Range("AB1").Value  '<-------ここでcm1がループせず上書になってしまう。
                    End If
                 Next
            Next

 この制御構造のところだけなので、ここだけをサンプルコードとして作って、短いVBAで検証・デバッグしたほうが
 効率がよくなる場合がある。あるいは、ここだけを【じっと見つめる】とか。

 新規ブックで、B1;B5に任意の値をいれて以下を実行して、結果の違いをみたうえで、両方のコードをじっと見比べてみて。

 Sub TestNG()
    Dim f As Range
    Dim t As Range

    For Each t In Range("A1:A5")
        For Each f In Range("B1:B5")
            t.Value = f.Value
        Next
    Next

 End Sub

 Sub TestOK()
    Dim f As Range
    Dim t As Range

    Set t = Range("A1")
    For Each f In Range("B1:B5")
        t.Value = f.Value
        Set t = t.Offset(1)
    Next

 End Sub

 (ぶらっと)


  ぶらっとさん いつもありがとうございます!

 >やりたかったことは、rm1内の各セル に、shfrommの行の中のOutlineLevelが2のものの AB列の値を 順番に書き込みたいということかな?
まさしく、そのとおりです! 
 こんなに長文だと読むだけでみなさま、いやになっちゃうだろうなぁと思いながらも・・すみません!!のSOSでした。
それなのにちゃんと読み取って、回答していただけて、大感謝しています。

 Test試してみました。私がネストしているつもりだったNGバージョンは、やっぱり上書きされてしまうんですね。
OKバージョンだと動くことを確認しました。これは、For Next構文のときに使う、転記先行=転記先行+1 みたいな感じですね。
実はFor Nextでも考えていたのですが、試行錯誤してもできず、挫折していました。

 それで、以下のように記述してみたのですが、ステップ実行で1行ずつだと上手く転記されて、MsgBox "転記終了"まで行くのに、いざ実行
してみると、どこにも転記されません??
・・・どーなっちゃったんでしょう?・・自分でももう少し考えます・・・が、もし、よろしかったら、間違っている点を教えていただけますか?
甘えてばかりで申し訳ありませんm(__)m

 Set cm1 = Range("D13") '項目Mの「仮」の当期欄 ※種別jのデータが今存在しないのでD13種別tの欄から転記とする
                 For Each myRow In shfromm.Range("A1").CurrentRegion.Rows
                    If myRow.OutlineLevel = 2 Then
                        cm1.Value = myRow.EntireRow.Range("AB1").Value
                        Set cm1 = cm1.Offset(1)
                    End If
                 Next

 さらに、ステップ実行で先に進んでみたところ、次の箇所で実行時エラー1004「ファイルにアクセルできません」とでます。
ファイルは確かにwbmを開いているので、存在するはずで、同じフォルダに同名のxlsファイルはないのですが、他に考えられる原因、ご指摘いただ
ければ、どうかお願いいたします。
 '転記元ブックm保存
    wbm.SaveAs Filepathm & sep & Left(shfromm.Range("A2"), 6) & shfromm.Range("Q2") & ".xls", FileFormat:=xlNormal

 (usamiyu)

 >いざ実行してみると、どこにも転記されません??

 確かにステップ実行するとうまくいくのに、普通に実行するとからぶりとか、もっと多くの場合はエラーになるとか
 そういうことは、ありうるけど、今回は、そのようなことになるコードにもなっていないので、実際には
 【ちゃんと転記されている】と思うね。ただし、【転記元ブックg】の、それを開いたときにたまたまアクティブに
 なっていたシートに。 Set cm1 = Range("D13") この D13 は、どこのD13かな?

 >実行時エラー1004「ファイルにアクセルできません」

 1004になる可能性については少し調べてみるけど、とりあえず、wbm.SaveAs の上に

 MsgBox Filepathm & sep & Left(shfromm.Range("A2"), 6) & shfromm.Range("Q2") & ".xls"

 をいれて、いま保存しようとしている名前(フルパス)が、意図した文字列になっているかどうかを
 確認してくれる?

 (ぶらっと)

 テーマとは関係がないけど

 > MsgBox "題名に今月を入力しましたか?"    'vbOKonlyにしておいて、忘れていたら入力する?Exitはしたくない

 ここで、まだ入力していなかったとしよう。で、OKボタンをおすね。
 でも、そこで入力することはできないねぇ。そのまま、コードは実行されてしまう。

 操作者にNo を許さないということなら、以下のような方法はあるけど。

 Sub Sample()
    Dim myText As String
    Dim msg As String

    myText = Range("A1").Value   'たとえば

    Do

        If Len(myText) = 0 Then
            msg = "題名が入力されていません。必ず入力してください"
        Else
            msg = "題名を確認し、間違っていれば修正願います"
        End If
        myText = Application.InputBox(msg, "題名入力ボックス", myText, Type:=2)
        If myText = "False" Then myText = ""
        If Len(myText) > 0 Then Exit Do

    Loop

 End Sub

 (ぶらっと)

 >wbm.SaveAs Filepathm & sep & Left(shfromm.Range("A2"), 6) & shfromm.Range("Q2") & ".xls", FileFormat:=xlNormal

 Filepathm は、最初のほうで、Filepathm = Application.GetOpenFilename("csvファイル,*.csv", , "mを開く") で取得しているね。
 だから たとえば、 c:\〇〇〇\csvファイル名.csv という文字列だろうね?
 Left(shfromm.Range("A2"), 6) が aaaaaa 、shfromm.Range("Q2") が xyz だったとしよう。
 そうすると、Filepathm & sep & Left(shfromm.Range("A2"), 6) & shfromm.Range("Q2") & ".xls" は

 c:\〇〇〇\csvファイル名.csv\aaaaaaxyz.xls  ということになるね?
 これは、ちょっと具合が悪くない?

 (ぶらっと)

  >Set cm1 = Range("D13") この D13 は、どこのD13かな?
わーっ!そうでしたね。きちんと修飾しなきゃいけなかったですね!なんだかどたばた混乱していて、すみません。
Set cm1 = .Range("D13")として、この点、解決しました。

 それから下記の件は、先にコメントいただいてしまいましたが、書いていたので、そのまま記載します。

 >MsgBox Filepathm & sep & Left(shfromm.Range("A2"), 6) & shfromm.Range("Q2") & ".xls"
ファイル名に余分なスペースが入っていたので、次のようにして、確認しました。
MsgBox Filepathm & sep & Left(shfromm.Range("A2"), 6) & RTrim(shfromm.Range("Q2")) & ".xls"

 すると次のようになっています。多分FilepathmのところでCSV形式のファイル名が入っているのがいけないのでしょうか?
 ・・・どうしたらいいのでしょう?
 D:\usamiyu\Report\○○¥25年度¥転記元ブックmの名前.csv¥201305△△.xls
                                                   ^^^^^^
                                                  /ココ??

 >操作者にNo を許さないということなら 
 なるほどぉ。自分がステップ実行していたからか、気づきませんでしたが、そこで入力することはできなかったんですね。
Sampleコードを参考にします。ありがとうございます。こういった処理は今までしたことがありませんでした。新しいことを
たくさん教えていただけて、楽しいです(^^)
 (usamiyu) 

 フルパス文字列からのパス情報の取出しを含んで参考コードを3つほど。
 TestA,TestB は実際のファイルがあってもなくても、単に文字列処理なのでエラーにはならないけど
 TestCは、実際のファイルを見に行っているので、なければエラーになる。

 Sub TestA()
    Dim fullPath As String
    Dim myPath As String
    Dim fNameShort As String
    Dim fNameLong As String
    Dim myExt As String
    Dim wk As Variant

    fullPath = "c:\aaaa\bbbb\cccc\XYZ.csv"

    wk = Split(fullPath, "\")
    fNameLong = wk(UBound(wk))
    myPath = Replace(fullPath, fNameLong, "")   '最後に \ がついているけど
    fNameShort = Split(fNameLong, ".")(0)
    myExt = Split(fNameLong, ".")(1)

    MsgBox "フルパス:" & fullPath & vbLf & _
           "パス:" & myPath & vbLf & _
           "ファイル名(拡張子付):" & fNameLong & vbLf & _
           "ファイル名(拡張子無):" & fNameShort & vbLf & _
           "拡張子:" & myExt

 End Sub

 Sub TestB()
    Dim fullPath As String
    Dim myPath As String
    Dim fNameShort As String
    Dim fNameLong As String
    Dim myExt As String
    Dim wk As Variant

    fullPath = "c:\aaaa\bbbb\cccc\XYZ.csv"

    With CreateObject("Scripting.FileSystemObject")
        myPath = .GetParentFolderName(fullPath)     '最後に \ はつかないけど
        fNameShort = .GetBaseName(fullPath)
        myExt = .GetExtensionName(fullPath)
        fNameLong = fNameShort & "." & myExt
    End With

    MsgBox "フルパス:" & fullPath & vbLf & _
           "パス:" & myPath & vbLf & _
           "ファイル名(拡張子付):" & fNameLong & vbLf & _
           "ファイル名(拡張子無):" & fNameShort & vbLf & _
           "拡張子:" & myExt

 End Sub

 Sub TestC()
    Dim fullPath As String
    Dim myFile As Object
    Dim myPath As String
    Dim fNameShort As String
    Dim fNameLong As String
    Dim myExt As String
    Dim wk As Variant

    fullPath = "c:\aaaa\bbbb\cccc\XYZ.csv"

    With CreateObject("Scripting.FileSystemObject")
        Set myFile = .getfile(fullPath)
        myPath = myFile.parentfolder.path           '最後に \ はつかないけど
        fNameLong = myFile.Name
        fNameShort = .GetBaseName(fullPath)
        myExt = .GetExtensionName(fullPath)
    End With

    MsgBox "フルパス:" & fullPath & vbLf & _
           "パス:" & myPath & vbLf & _
           "ファイル名(拡張子付):" & fNameLong & vbLf & _
           "ファイル名(拡張子無):" & fNameShort & vbLf & _
           "拡張子:" & myExt

 End Sub

 (ぶらっと)

 操作者にNo をさせないということで、Sampleコードを参考にして、画面描画停止したすぐ次の行に以下のように挿入してみました。
上手くいった?みたいです。  
  '--------------------------------------------------------
    '題名に月数を入力したか確認して入力を促す
    '--------------------------------------------------------
    With shtod
        myText = .Range("L1").Value   '報告月
        Do
            If Val(Left(myText, 1)) <> Val(Month(Date)) Then        '記載してある月が今月と違ったら
                msg = "月数が入力されていません。必ず入力してください"
            End If
            myText = Application.InputBox(msg, "月数入力ボックス", myText, Type:=2)
            If myText = "False" Then myText = ""
            If Val(Left(myText, 1)) = Val(Month(Date)) Then .Range("L1").Value = myText
            Exit Do
         Loop
     End With

 それから、フルパス文字列からのパス情報の取出し、TestBを使ってみました。
「転記元、転記先ブックを保存する」以降のコードを次のように書き換えて、一応、最後まで完成しました。本当にありがとうございます!

   '転記元ブックm保存
    With CreateObject("Scripting.FileSystemObject")
        myPath = .GetParentFolderName(Filepathm)
    End With

    wbm.SaveAs myPath & sep & Left(shfromm.Range("A2"), 6) & RTrim(shfromm.Range("Q2")) & ".xls", FileFormat:=xlNormal
    wbm.Close False

     '転記元ブックg保存
    With CreateObject("Scripting.FileSystemObject")
        myPath = .GetParentFolderName(Filepathg)
    End With

    wbg.SaveAs myPath & sep & Left(shfromg.Range("A2"), 6) & RTrim(shfromg.Range("Q2")) & ".xls", FileFormat:=xlNormal
    wbg.Close False

    Application.ScreenUpdating = True  '画面描画再開

    '調査票様式ブックを同じフォルダにA1セルの名前で保存
    With CreateObject("Scripting.FileSystemObject")
        myPath = .GetParentFolderName(FilePatht)
    End With

    With wbt
        .SaveAs myPath & sep & Sheets(1).Range("A1") & ".xls"
        .Sheets(1).PrintPreview
        .Sheets(1).PrintOut
        .Close
    End With 

 (usamiyu) 

  ぶらっとさん、完成はしました。したのですが・・・もう少しの間、質問をつづけてもいいですか?
しつこくて申し訳ありません。(汗)
 もし、いい加減にして!と思われていたら、そう言ってくださると助かります。とりあえず、続けます。

 この保存部分のコード、ブックが違うけれど、似たようなことを3回やっているのですが、サブルーチン化するとしたら、どうしたら
よいのでしょうか。

 最初、wbmとwbgについては保存方法がまったく同じなので、次のようにサブルーチンを書いてみました。
エラーは出ず、コードのとおり閉じたのですが、XL形式で保存されたファイルが見当たりません。他のフォルダも探してみましたが、
ない・・みたいです。

 親プロシージャ
 Call Get_Mypath(wbm As Workbook, Filepathm As Variant, shfromm As Worksheet)
 Call Get_Mypath(wbg As Workbook, Filepathg As Variant, shfromg As Worksheet)

 子プロシージャ
 Private Sub Get_Mypath(wb As Workbook, Filepath As Variant, shfrom As Worksheet) 
    Dim myPath As String
    Dim sep As String

    With CreateObject("Scripting.FileSystemObject")
        myPath = .GetParentFolderName(Filepath)     '最後に \ はつかない
    End With

    wb.SaveAs myPath & sep & Left(shfrom.Range("A2"), 6) & RTrim(shfrom.Range("Q2")) & ".xls", FileFormat:=xlNormal
    wb.Close False
 End Sub

 そもそも今回のメインコード、ブラッシュアップするとしたら、転記処理の部分自体もサブルーチン化できそうですよねぇ。
 質問に来る前は混乱して、とてもそこまで手が回っていなかったんですが、ちょっと欲がでてきちゃいました^^;

 (usamiyu)

 全然、迷惑なんてことないので気にしないでね。
 usamiyuさんの探求心と向上心、大好きですから。

 テスト環境が事務所のPCにおいたままなので、明日まで待ってくれる?

 (ぶらっと)

 ぶらっとさん・・ありがとうございます!!
嬉しくて、ありがたすぎて、泣けてきます〜。

 はい、もちろんです。明日、またお話できるのを楽しみにしています^^

 (usamiyu)

 ちょっとばたばたしていて、今日、取組む時間がとれなかった、ごめん。

 とりあえず、例のごとく

 wb.SaveAs myPath & sep & Left(shfrom.Range("A2"), 6) & RTrim(shfrom.Range("Q2")) & ".xls", FileFormat:=xlNormal

 のまえに、

 MsgBox myPath & sep & Left(shfrom.Range("A2"), 6) & RTrim(shfrom.Range("Q2")) & ".xls"

 をいれて、表示される文字列をメモして、処理後、その文字列のファイルが保存されていないかどうかを
 確認してみよう。

 ところで

 Call Get_Mypath(wbm As Workbook, Filepathm As Variant, shfromm As Worksheet)

 これは、コンパイルエラーになると思うけど? 実際には

 Call Get_Mypath(wbm, Filepathm, shfromm)

 このように書いているんだよね?

 (ぶらっと)

 おつかれさまです。お忙しい中、お疲れのところ、お気に留めていただいて恐縮です。
私もちょうど、ごたついていたので、あれこれ片付けられて、かえってよかったです(^^)

 >実際にはCall Get_Mypath(wbm, Filepathm, shfromm)このように書いているんだよね?

 はいそうです。それで下記を確認してみました。
 MsgBox myPath & sep & Left(shfrom.Range("A2"), 6) & RTrim(shfrom.Range("Q2")) & ".xls"

 !あぁぁ・・・凡ミスです。sep = Application.PathSeparator が抜けていました。すみません。
 こうするときちんと保存されました。

 なので、とりあえずwbmとwbgについての保存はサブルーチン化できました。

 wbtもなんとかできるでしょうか?

 それと転記処理の部分もrm1、rm2、rg1、rg2として、同じような処理をしているので、ここもサブルーチンでなんとか
なりそうでしょうか?

 ※お返事は急ぎません。ご都合のよいときにお願いできたらと思います。

 (usamiyu)

 すみません。↑の訂正です。

 誤 rm1、rm2、rg1、rg2

 正 cm1、cm2、cg1、cg2 

 (usamiyu)

 転記処理の部分のサブルーチン化、次のようにしてみました。
 とりあえずできたみたいですが、こんな感じの引数でまとめればいいのでしょうか?

 親プロシージャ 
        Set cm1 = .Range("D13") '項目Mの「仮」の当期欄 ※種別jのデータが今存在しないのでD13種別tの欄から転記とする
        Set cm2 = .Range("G13") '項目Mの「支出」の当期欄 ※種別jのデータが今存在しないのでG13種別tの欄から転記とする
        Set cg1 = .Range("D19") '項目Gの「仮」の当期欄 ※種別jのデータが今存在しないのでD19種別tの欄から転記とする
        Set cg2 = .Range("G19") '項目Gの「支出」の当期欄 ※種別jのデータが今存在しないのでG19種別tの欄から転記とする

        Call Transfer_To_Report(cm1, cm2, shfromm)
        Call Transfer_To_Report(cg1, cg2, shfromg)

 子プロシージャ
 Private Sub Transfer_To_Report(c1 As Range, c2 As Range, shfrom As Worksheet)
    Dim myRow As Range

    For Each myRow In shfrom.Range("A1").CurrentRegion.Rows
        If myRow.OutlineLevel = 2 Then
            c1.Value = myRow.EntireRow.Range("AB1").Value
            Set c1 = c1.Offset(1)
        End If
    Next

    For Each myRow In shfrom.Range("A1").CurrentRegion.Rows
        If myRow.OutlineLevel = 2 Then
            c2.Value = myRow.EntireRow.Range("AE1").Value
            Set c2 = c2.Offset(1)
        End If
    Next

 End Sub

 (usamiyu)

 親子関係の記述はこれで問題ないと思うね。

 サブプロシジャ側、これでも、まったく問題ないけど、以下のように記述することもできるかな?

 Private Sub Transfer_To_Report(c1 As Range, c2 As Range, shfrom As Worksheet)
    Dim myRow As Range

    For Each myRow In shfrom.Range("A1").CurrentRegion.Rows
        If myRow.OutlineLevel = 2 Then
            c1.Value = myRow.EntireRow.Range("AB1").Value
            c2.Value = myRow.EntireRow.Range("AE1").Value
            Set c1 = c1.Offset(1)
            Set c2 = c2.Offset(1)
        End If
    Next

 End Sub

 (ぶらっと)

  ああ!C1もC2も同じmyRowの中だからまとめられるんですねぇ。ありがとうございます。まとめます。
ご指摘いただけると「なるほど」と思うのですが、自分だと気づかないんです。つめが甘いですね。

 それからwbtに関してはサブルーチン化する必要がない気がしてきましたので、このままとするつもりです。

 最後にもうひとつ気になっている点、教えていただけますか。
(あ、再確認ですが、お返事はゆっくりで、もしよろしければということで構いません。)

 上のほうのレスで >'題名に月数を入力したか確認して入力を促す  というコードを記載したのですが、
題名に月数が入っていて、これは今月の数字と違っていたら入力を促すという目的で書いています。
その中で
If Val(Left(myText, 1)) <> Val(Month(Date)) Then 

 としているのですが、これだと  Left(myText, 1) で抜き出しているので、1〜9月はいいのですが、10月以降だと
比較できなくなっちゃいますよね。それで今 Val(Left(myText, 2))としました。

 もともとVal関数を使ったのは、イミディエイトウィンドウでLeft(myText, 1) = Month(Date) としてみたら月数が
同じでもFalseが返ってきたので、Valで数値にしてみたのですが、LeftとMonth関数をヘルプで見てみるとどちらも
同じバリアント型の値を返すとあります。ただ内部形式はそれぞれStringとIntegerのVariantとあるので、この二つは
比較できないということなのでしょうか?

 (usamiyu)

 比較はできるよ。大丈夫。
 ただし、Val(Left(myText, 2)) でもいいけど、文字列最初が 5月・・・ や 10月・・・になっているなら Val(MyText) でもい。 

  Sub Test1()
    Dim s As String

    s = "10月 あいうえお"

    If Val(s) = Month(Date) Then
        MsgBox "EQ"
    Else
        MsgBox "NE"
    End If

    s = "5月 あいうえお"

    If Val(s) = Month(Date) Then
        MsgBox "EQ"
    Else
        MsgBox "NE"
    End If

 End Sub

 Sub Test2()
    Dim s As String

    s = "10月 あいうえお"

    If Val(Left(s, 2)) = Month(Date) Then
        MsgBox "EQ"
    Else
        MsgBox "NE"
    End If

    s = "5月 あいうえお"

    If Val(Left(s, 2)) = Month(Date) Then
        MsgBox "EQ"
    Else
        MsgBox "NE"
    End If

 End Sub

 (ぶらっと)

  試してみました。なるほどValを使うならTest1の形でいけますね。
でも  >文字列最初が 5月  でないとだめなんですね。
s = "かきく5月 あいうえお"  としてみたら "NE" になっちゃいました。最初に数値がないとだめってことなんでしょうか?
Val(s)が0になってしまいました。??

 実は様式に記載してある題名は、A1からI1まで結合して、「平成25年度 ○○報告(   5月分)」というようなもので、
ここから月数の判定をする方法がわからなかったので、仕方なく、様式ブックの欄外の列に( 以前と ( より後で値を分割して、
L1に  5月分)  といった形で記載して、欄内はこれをconcatenate関数でくっつけて、しのぎました。
 こんなことせずに判定する方法もありますか?

 (usamiyu)


 最初に 、「平成25年度 ○○報告(   5月分)」といった文字列を見たときに、「扱いにくそう」と感じた。
 この文字列は、それぞれ単独の項目が入っているセルを連結しているということなら、自分なら、年月を日付型で入力するセルを作っておき
 その日付型のデータから、Text関数も含んだ連結処理(ないしは、VBAで文字列を作り出し)をするね。そうすれば、文字列の中から
 月を抽出しなくても、この日付セルの年月とDateをストレートに比較できるので。

 と思うけど、コード案を2種類。(TestX と TestY)

 Sub TestX1()
    Dim s As String
    Dim n As Long
    Dim m As Long

    ' ( より後ろの文字列
    s = "   5月分)"
    n = InStr(s, "月")
    If n > 0 Then
        If IsNumeric(Mid(s, n - 2, 1)) Then
            m = Val(Mid(s, n - 2, 2))
        Else
            m = Val(Mid(s, n - 1, 1))
        End If
    End If

    MsgBox m

 End Sub

 Sub TestX2()
    Dim s As String
    Dim n As Long
    Dim m As Long

    ' ( より後ろの文字列
    s = "   10月分)"
    n = InStr(s, "月")
    If n > 0 Then
        If IsNumeric(Mid(s, n - 2, 1)) Then
            m = Val(Mid(s, n - 2, 2))
        Else
            m = Val(Mid(s, n - 1, 1))
        End If
    End If

    MsgBox m

 End Sub

 Sub TestY1()
    Dim s As String
    Dim mt As Object

    Dim n As Long
    Dim m As Long

    ' 文字列全体
    s = "平成25年度 ○○報告(   5月分)"

    With CreateObject("VBScript.RegExp")
        .Pattern = "(\d{1,2})月"
        Set mt = .Execute(s)
        If mt.Count Then
            m = mt.Item(0).submatches(0)
        End If
    End With

    MsgBox m

 End Sub

 Sub TestY2()
    Dim s As String
    Dim mt As Object

    Dim n As Long
    Dim m As Long

    '文字列全体
    s = "平成25年度 ○○報告(   10月分)"

    With CreateObject("VBScript.RegExp")
        .Pattern = "(\d{1,2})月"
        Set mt = .Execute(s)
        If mt.Count Then
            m = mt.Item(0).submatches(0)
        End If
    End With

    MsgBox m

 End Sub

 (ぶらっと)

  扱いにくいですよね。
 様式ブックの形式は私が変えるものではないのですが、報告提出後、本部では複数支店の報告をまとめて、
最終形を作るだろうと推測されるので、題名をちょっといじっても、大勢に影響ないだろうと思い、文字列を
分割しました。

 >自分なら、年月を日付型で入力するセルを作っておき その日付型のデータから、Text関数も含んだ連結処理
 >(ないしは、VBAで文字列を作り出し)をするね。

 それで、コード案も試してみたのですが、上のお言葉のように処理してみたいです。
 自分でできないかと考えたのですが・・・すみません。勉強不足でできません _(._.)_
 散々教えていただいているのに、ほんとに自分でも情けないんですが、もう少しだけ教えていただけるでしょうか。

 おっしゃっているのは、こういうことではないのでしょうか?
 まず、たとえばJ1に 4/1と入れて、表示形式を2013年4月にしておく。
 それで、題名の部分は A1に =TEXT(J1,"ggge""年度""") & " ○○報告(" & TEXT(J1,"    m""月末現在)""")とする。

 その後がわからないのですが、>日付セルの年月とDateをストレートに比較する  というのはどうしたら??
 たとえば、下記のようにすると J1の値は表示形式で年月にしているだけなので、ストレートに比較ってできないのですが、
 そもそも、J1セルの設定の仕方がまちがっていますか?

        myText = .Range("J1").Value   '報告月
            If myText <> Date Then  
 (usamiyu)

 たとえば

 Sub Sample1()  'J1表示書式がyyyy年m月

    Range("J1").Value = DateSerial(2013, 5, 1)

    If Format(Date, "yyyy年m月") = Range("J1").Text Then
        MsgBox "EQ"
    Else
        MsgBox "NE"
    End If

     Range("J1").Value = DateSerial(2013, 4, 1)

    If Format(Date, "yyyy年m月") = Range("J1").Text Then
        MsgBox "EQ"
    Else
        MsgBox "NE"
    End If

 End Sub

 Sub Sample2()  'J1表示書式を問わない

    Range("J1").Value = DateSerial(2013, 5, 1)

    If Format(Date, "yyyy年m月") = Format(Range("J1").Value, "yyyy年m月") Then
        MsgBox "EQ"
    Else
        MsgBox "NE"
    End If

     Range("J1").Value = DateSerial(2013, 4, 1)

    If Format(Date, "yyyy年m月") = Format(Range("J1").Value, "yyyy年m月") Then
        MsgBox "EQ"
    Else
        MsgBox "NE"
    End If

 End Sub

 (ぶらっと)

  ぶらっとさん ありがとうございます。
そうでしたかぁ・・Format関数で取り出して、ポイントはTextプロパティで比較するっていうことなんですね。
 ValueとTextの違い、よくわかっていませんでした。おさらいします。昨夜は(@_@)状態でSOSしてしまい、失礼しました。

 sample1を次の用に組み込んで、上手くいきました。

 With shtod
        Do
            If .Range("J1").Text <> Format(Date, "yyyy年m月") Then        '記載してある月が今月と違ったら
                msg = "月数が入力されていません。必ず入力してください"
            End If
            .Range("J1").Value = Application.InputBox(msg, "月数入力ボックス", .Range("J1").Text, Type:=2)
            If .Range("J1").Value = "False" Then .Range("J1").Text = ""
            If .Range("J1").Text = Format(Date, "yyyy年m月") Then Exit Do
         Loop
 End With

 今回はお忙しいのに食い下がってしまい、大変ご面倒をおかけしました。やっと納得がいきました。心から感謝しています。
ありがとうございました。
 私の探究心?にあきれはてて、もうかかわりたくないと思っていらっしゃるのではないかと不安ですが、
どうかこれに懲りず、次回もまた、ご指導くださいね。ね?

 (usamiyu@ぶらっとさんファンの1人♪)

こんにちは。

解決後にお邪魔します。
最後の部分ですが、当月以外を許さないなら、わたしならこうします。
操作者の手を煩わす必要はありません。

  With shtod
    If .Range("J1").Text <> Format(Date, "yyyy年m月") Then        '記載してある月が今月と違ったら
      'MsgBox "J1に本日の日付をセットします"                        'メッセージを出す方が親切?
      .Range("J1").Value = Date
    End If
  End With

−佳−


  佳さん こんにちは〜。またお話できて嬉しいです。ありがとうございます。

 確かにおっしゃるとおりですねぇ。
 >当月以外を許さないなら、
 この方がいいですね。

 それで、私もこのロジックにしていたのですが、ちょっと、悩んでいるのは、
締め切りを守る人は、このロジックだと、すっと転記されて楽なんですが、
何かの事情で締め切りを守らず、当月以内に報告を出せなかった場合、どうしようかなぁと。
もう少し、自分でロジックを考え直す必要があると思っています。

 (usamiyu)


 ぶらっとさん 佳さん

 上の件、悩んだ結果、意図する月数と違ったらExitさせることにしました。
一応、次のような結果になったので、アップしてみます。でも操作者にNoをさせないコードも勉強になりました。
 ご指導ありがとうございました。

     '--------------------------------------------------------
    '報告月を確認する
    '--------------------------------------------------------
    With shtod
        myMonth = .Range("J1").Text
        If MsgBox("月数は" & myMonth & "これでいいですか?", vbQuestion + vbYesNo, "報告月確認") = vbYes Then

          '題名を埋め込む
           .Range("A1").Value = Format(.Range("J1"), "ggge年度") & "報告(      " & Month(.Range("J1")) & "月末現在)"

          'YesならshikkouseiriListを子プロシージャから呼ぶ
           Call ShikkouseiriList(shfromm)
           Call ShikkouseiriList(shfromg)

        Else
           Exit Sub  
        End If      
    End With

 (usamiyu)

コメント返信:

[ 一覧(最新更新順) ]


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