- ベストアンサー
VBAで条件に一致するセルの隣の値をまとめる方法
- VBAを使用して、条件に一致する複数のセルの隣のセルの値を取得し、まとめる方法を教えてください。
- 商品コードとサイズ値が入力されたデータがあるA列とB列があります。条件に一致する商品コードのサイズ値を別のシートでまとめたいです。
- COUNTIF関数とMATCHやINDEX関数を使用して抽出し、まとめる方法で実現できますが、処理に時間がかかります。VBAならより高速に処理できる方法があるか教えてください。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
>データが8万行ほどあり ちんたらやってると、手でやるより遅くなります。 #1行目タイトル行、2行目からデータとする sub macro1() dim lastRow as long ’準備 lastrow = cells(rows.count, "A").end(xlup).row range("A:B").sort key1:=range("A1"), order1:=xlascending, header:=xlyes range("C:C").insert shift:=xlshifttoright range("C2:C" & lastrow).formula = "=IF(A1=A2,C1&"":"","""")&B2" ’コード抽出 range("E:F").insert shift:=xlshifttoright range("A:A").advancedfilter action:=xlfiltercopy, copytorange:=range("E1"), unique:=true ’結果転記 lastrow = cells(rows.count, "E").end(xlup).row with range("F2:F" & lastrow) .formula = "=VLOOKUP(E2,A:C,3)" .value = .value end with range("C:C").delete shift:=xlshifttoleft end sub
その他の回答 (2)
- MackyNo1
- ベストアンサー率53% (1521/2850)
>処理にかなりの時間を要するのでVBAならもっと高速にできるのではないかと思い質問させて頂きました。 使用する関数の組み合わせなどに影響しますが、一般にエクセルに用意されている関数はプログラムが洗練されているため、極めて処理速度が速いので、必ずしもVBAで処理速度を向上できるとは限りません。 ただし再計算に時間がかかる場合はシートの動きが重くなるので計算方法を手動などにする必要があります。 このようなケースではピボットテーブルの機能を利用するのがお勧めです。 データ範囲をホームタブの「テーブルとして書式設定」でテーブルにしておき(この操作でデータの追加に自動対応します)、挿入タブのピボットテーブルで行フィールドに商品コード、列フィールドとΣ値(データフィールド)にサイズをドラッグしてピボットテーブルを完成させ、テーブル上で右クリックし「ピボットテーブルオプション」の集計とフィルタタブで列と行の総計を表示するのチェックを外します(添付画像の左側のテーブル)。 テーブルの右側の適当なセルに()添付画像ではK5セルに以下の式を入力し下方向にオートフィルコピーします。 =IF(B5,B$4&" ","")&IF(C5,C$4&" ","")&IF(D5,D$4&" ","")&IF(E5,E$4&" ","")&IF(F5,F$4&" ","") これで、適宜不要な列(B列からJ列)を選択して右クリックから「非表示」にすればご希望の集計データになっています。 ちなみに、提示した数式はサイズ数の種類が最大5つある場合ですので、必要に応じて適宜関数をつなげてください。 また、区切り文字は全角スペースにしてありますが、コロンにしたい場合は以下のように数式を変更してください。 =SUBSTITUTE(TRIM(IF(B5,B$4&" ","")&IF(C5,C$4&" ","")&IF(D5,D$4&" ","")&IF(E5,E$4&" ","")&IF(F5,F$4&" ",""))," ",":")
お礼
ピボットテーブルを使うという発想は思い浮かびませんでした! 今後の参考とさせて頂きます。 ありがとうございました。
- tom04
- ベストアンサー率49% (2537/5117)
こんにちは! 一例です。 標準モジュールに↓のコードをコピー&ペーストしてマクロを実行してみてください。 (Sheet1のデータをSheet2に表示するようにしてみました) Sub Sample1() 'この行から Dim i As Long, c As Range, wS As Worksheet Set wS = Worksheets("Sheet2") wS.Range("A:B").ClearContents With Worksheets("Sheet1") .Range("A:A").AdvancedFilter , Action:=xlFilterInPlace, unique:=True .Range("A:A").Copy wS.Range("A1") .ShowAllData For i = 2 To .Cells(Rows.Count, "A").End(xlUp).Row Set c = wS.Range("A:A").Find(what:=.Cells(i, "A"), LookIn:=xlValues, lookat:=xlWhole) If wS.Cells(c.Row, "B") = "" Then wS.Cells(c.Row, "B") = .Cells(i, "B") Else wS.Cells(c.Row, "B") = wS.Cells(c.Row, "B") & ":" & .Cells(i, "B") End If Next i End With End Sub 'この行まで こんな感じではどうでしょうか?m(_ _)m
お礼
早速のご回答ありがとうございます! もちろんPCのスペックも関係あるとは思いますが、7万行弱のデータで動かしてみたら処理に10分以上掛ってしまいました。 VBAも書き方一つで処理速度は大幅に違うようですね。 参考とさせて頂きます。 ありがとうございました。
お礼
一瞬で求めていたデータが弾き出されました! 大変助かりました! ありがとうございます。