各シートから値を抽出する

中級VBA

各シートから値を抽出する

 Excelで業務を行っていると、各所に散らばったデータをまとめて抽出したい事があります。
 ここでは、各シートから特定の部分を抜き出して、「抽出」というシートにまとめる例を示していきます。
 
 データの抽出作業では、抽出するための条件設定も大事ですが、データ抽出しないための設定も重要です。
 この事に注目してコードを見てみましょう。

サンプルデータを用意

 今回はプログラム用に、抽出元となるサンプルのデータシートを用意します。
 ここではわかりやすいように、「シート番号 行番号 : 列番号」をそれぞれのセルに書き込んで、きちんと抽出されたか確認できるようにします。

 シートをいくつか作成して、各シートをアクティブにした状態で、以下のコードを実行してください。

Sub mark()
    Dim i As Long, j As Long
    
    For i = 1 To 50
        For j = 1 To 50
            Cells(i, j) = ActiveSheet.Index & " " & i & ":" & j
        Next j
    Next i
    
End Sub

 実行すると以下のようにセルにデータが配置されます。

 更に、データの無いシートと「抽出」という名前の抽出用シートも用意しておきましょう。

決まった行と列で抽出していく

 規則性のある、特定の行、列にあるデータを抽出したい時の例です。
 
 ここでは、3行目から9行おきに並ぶ B,D,L列をそれぞれ、「抽出」シートのA,B,C列にコピーしています。
 
 行に関しては、 trg 変数がコピー元。cnt 変数がコピー先を指定しています。
 trg 変数は最初にオフセットとして3行目で初期化し、その後は9行づつ追加していきます。
 コピー先はcnt 変数が、1行目から逐次追加されていきます。

Sub sample1()
    Dim i As Long
    Dim cnt As Long, trg As Long
    
    Dim sh As Worksheet
    Set sh = Worksheets("抽出")
    
    cnt = 1
    For i = 1 To Worksheets.Count
        
        If Worksheets(i).Name = "抽出" Then GoTo LABEL
        
        If Worksheets(i).Range("A1") = "" Then GoTo LABEL
        
        With Worksheets(i)
        trg = 3
        Do While .Cells(trg, "A") <> ""
            sh.Cells(cnt, "A") = .Cells(trg, "B")
            sh.Cells(cnt, "B") = .Cells(trg, "D")
            sh.Cells(cnt, "C") = .Cells(trg, "L")
            trg = trg + 11
            cnt = cnt + 1
        Loop
       
        End With
LABEL:
    Next i
End Sub

 全体として 変数 i がシートの数だけループしていきます。
 その際、「抽出」シートは除外しています。
 また、シートのA1に値が無い場合は、データシートではないと見なしてこちらも除外しています。
 どちらも GoTo LABEL で処理を飛ばしています。
 
 さらに、以下のように Do While でA列に値がなくなるまで繰り返しています。

 Do While .Cells(trg, “A”) <> “”

行単位の抽出

 行を抜き出す場合は、転記するのではなく copy コマンドを使用する事になります。
 書き方は何通りかありますが、今回は、Rows(行番号) を使った例を示します。
 ここでは 9行目、12行目、20行目、23行目、31行目、34行目、、、
 という順でコピーしています。
 
 除外の例は、上記のサンプルと同じなので省略します。

Sub sample2()
    Dim i As Long
    Dim cnt As Long, trg As Long
    
    Dim sh As Worksheet
    Set sh = Worksheets("抽出")
    
    cnt = 1
    For i = 4 To Worksheets.Count
        
        If Worksheets(i).Name = "抽出" Then GoTo LABEL
        
        If Worksheets(i).Range("A1") = "" Then GoTo LABEL
        
        With Worksheets(i)
        trg = 9
        Do While .Cells(trg, "A") <> ""
            .Rows(trg).Copy sh.Rows(cnt)
            cnt = cnt + 1
            .Rows(trg + 3).Copy sh.Rows(cnt)
            cnt = cnt + 1
            
            trg = trg + 11
        Loop
        End With
LABEL:
    Next i
End Sub

条件を定義して抽出

 今度はIf文で、セルの値で条件分岐して抽出する方法を見ていきましょう。
 今回は、A列に ”3:1″ という文字列が含まれている条件で行を抽出します。
 ある文字列が含まれている条件は、InStr関数を使うのが定番です。
 InStr関数は、第一引数の文字列の中に、第二引数の文字列が含まれている場合、その位置を数値で返してくれます。
 もし、含まれていない場合は、0が返ってくるので、これを利用します。
 
 結果的に、3行目、13行目、23行目、、、という感じでヒットします。

Sub sample3()
    Dim i As Long
    Dim cnt As Long, trg As Long
    
    Dim sh As Worksheet
    Set sh = Worksheets("抽出")
    
    cnt = 1
    For i = 4 To Worksheets.Count
        
        If Worksheets(i).Name = "抽出" Then GoTo LABEL
        
        If Worksheets(i).Range("A1") = "" Then GoTo LABEL
        
        With Worksheets(i)
        
        trg = 1
        Do While .Cells(trg, "A") <> ""
            If InStr(.Cells(trg, "A"), "3:1") > 0 Then  ’条件分岐
                .Rows(trg).Copy sh.Rows(cnt)
                cnt = cnt + 1
            End If
            trg = trg + 1
        Loop
   
        End With
LABEL:
    Next i
End Sub

 条件分岐に関しては、色々なバリエーションが考えられるので、アイデア次第で用途が広がっていくと思います。

まとめ

 データ抽出の例を3つ見てきました。
 データの並びや特徴を見つけて、それに合わせて条件分岐していきます。
 最初の例では、行が規則的で、列が決まっている場合。
 次の例では、行が規則的で、その行を全て。
 最後の例では、セルの値を見て条件と照らし合わせる場合。
 これらは、Do While の内部で条件を設定すればOKでした。
 
 その他に、「抽出」シートやデータが存在しないシートを除外する処理を加えておくことも大事です。(GoTo LABEL の部分ですね。)

 データを抽出するというシチュエーションは、Excelで業務を行っているとよく出てきます。
 複雑そうに見えますが、基本を押さえていれば初心者でも出来ますので、是非挑戦してみてください。

タイトルとURLをコピーしました