• ベストアンサー

Excel VBAでグループ毎に集計する方法

ExcelのVBAについて教えてください。 A列 B列 OK 9/21 OK 9/21 NG 9/20 OK 9/20 NG 9/21 とセルに入力されていたときに、各日付ごとにOK、NGの発生回数を出す 場合はどのようにすれば良いのでしょうか? 9/20 OK:1個、NG:1個 9/21 OK:2個、NG:1個 大量のデータを扱うため、できるだけ早い処理方法で実現できる方法を希望しています。

質問者が選んだベストアンサー

  • ベストアンサー
  • _Kyle
  • ベストアンサー率78% (109/139)
回答No.4

日付順にソートして上から見ていくのが普通の手法ですが できるだけ早い処理方法で、ということなので、少し捻ってみました。 ・データ数 : 6万行 ・日付 : 2009/1/1 ~ 2009/12/31 の間でランダム の場合、私の環境だと0.2秒ほどで結果が出ます。 '=====↓ ココカラ ↓================================================ Sub Sample()  Dim orgAry  As Variant  Dim sumAry() As Long  Dim dayCnt  As Long  Dim rtnAry() As Long  Dim i    As Long  Dim j    As Long    'とりあえず1982年から2036年まで対応  ReDim sumAry(30000 To 50000, 0 To 2)    'アクティブシートの、A:B列のデータを読み込む  With ActiveSheet   orgAry = Intersect(.UsedRange, .Range("A:B")).Value  End With    For i = 1 To UBound(orgAry, 1)   If sumAry(orgAry(i, 2), 0) = 0 Then    sumAry(orgAry(i, 2), 0) = 1    dayCnt = dayCnt + 1   End If   Select Case orgAry(i, 1)    Case "OK": sumAry(orgAry(i, 2), 1) = sumAry(orgAry(i, 2), 1) + 1    Case "NG": sumAry(orgAry(i, 2), 2) = sumAry(orgAry(i, 2), 2) + 1   End Select  Next i    ReDim rtnAry(1 To dayCnt, 1 To 3)  j = 1  For i = LBound(sumAry, 1) To UBound(sumAry, 1)   If sumAry(i, 0) = 1 Then    rtnAry(j, 1) = i    rtnAry(j, 2) = sumAry(i, 1)    rtnAry(j, 3) = sumAry(i, 2)    j = j + 1   End If  Next i    'アクティブシートのC1セル以下に結果を書き出す  With ActiveSheet   .Range("C1").Resize(dayCnt, 3).Value = rtnAry   .Range("C1").Resize(dayCnt, 1).NumberFormatLocal = "yyyy/mm/dd"  End With   End Sub '=====↑ ココマデ ↑================================================ 以上ご参考まで。

tomy01
質問者

補足

_Kyle様 お礼が遅くなり申し訳ございません。 教えていただいたマクロで試したところ、とても早くてびっくりです。 本当にありがとうございます。 OK,NG以外(AA,BB,CC)に複数の判定をする場合は、そうしたらよいのでしょうか?いろいろ試してみましたがうまく動きませんでした。

その他の回答 (3)

  • hotosys
  • ベストアンサー率67% (97/143)
回答No.3

Sheet1のデータをSheet2に集計します。 元データの1行目に見出しが無ある場合は、見出し行を作る部分は不要です。 Sub sample() Dim srcSheet As Worksheet Dim dstSheet As Worksheet Dim lastRow As Long Set srcSheet = Sheets("Sheet1") '元データシート Set dstSheet = Sheets("Sheet2") '集計シート dstSheet.Cells.Clear '集計シートクリア srcSheet.Columns("A:B").Copy dstSheet.Range("A1") '元データを集計シートにコピー dstSheet.Rows(1).Insert 'フィルタを使うために見出しが必要なので、見出し行を挿入 dstSheet.Range("B1").Value = "日付" '見出を「日付」にする lastRow = dstSheet.Range("A" & Rows.Count).End(xlUp).Row 'A列を基準に最終行を取得 dstSheet.Range("C2:C" & lastRow).Formula = "=A2&B2" 'countifを使うための作業データをC列に作成 dstSheet.Columns("B").AdvancedFilter Action:=xlFilterCopy, CopyToRange:=dstSheet.Range("D1"), Unique:=True '[データ][フィルタ][フィルタオプションの設定]で日付を重複を削除してD列に dstSheet.Columns("D").Sort Key1:=dstSheet.Range("D2"), Order1:=xlAscending, Header:=xlYes 'D列を並び変える lastRow = dstSheet.Range("D" & Rows.Count).End(xlUp).Row 'D列を基準に最終行を取得 dstSheet.Range("E2:E" & lastRow).Formula = "=COUNTIF(C:C,""OK""&D2)" 'E列にOKを数える関数を設定 dstSheet.Range("F2:F" & lastRow).Formula = "=COUNTIF(C:C,""NG""&D2)" 'F列にNGを数える関数を設定 dstSheet.Range("E2:F" & lastRow).Copy '計算式を値にするためにコピー dstSheet.Range("E2:F" & lastRow).PasteSpecial xlPasteValues '値のみ貼り付け dstSheet.Columns("A:C").Delete 'A:C列を削除 dstSheet.Range("B1").Value = "OK" 'B列の見出し dstSheet.Range("C1").Value = "NG" 'C列の見出し dstSheet.Range("A1").Select 'A1を選択(コピーの時の範囲が選択されているので) End Sub

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.2

>できるだけ早い処理方法 だったら、 (1)メニューのデーター集計 例 日付 グループ 計数 結合 2009/9/20  1 1 400761 2009/9/20 2 4 400762 2009/9/20 2 2 400762 2009/9/21  1 3 400771 2009/9/21  1 2 400771 2009/9/22  2 4 400782 D列はD2に=A2&B2 を入れて下方向に式を複写 「結合」列でソート メニューのデーター集計 グループの基準 結合 集計の方法 合計 この画相質問では「データの個数」 集計するフィールド どの項目でもよいーOK 結果 日付 グループ 計数 結合 2009/9/20 1 1 400761 1 400761 データの個数 2009/9/20 2 4 400762 2009/9/20 2 2 400762 2 400762 データの個数 2009/9/21 1 3 400771 2009/9/21 1 2 400771 2 400771 データの個数 2009/9/22 2 4 400782 1 400782 データの個数 6 総合計 折りたためば、合計件数だけになる。 また結合列の式を=TEXT(A2,"yyyy/mm/dd")&" "&B2のようにすれば 日付 グループ 計数 結合 2009/9/20 1 1 2009/09/20 1 1 2009/09/20 1 データの個数 2009/9/20 2 4 2009/09/20 2 2009/9/20 2 2 2009/09/20 2 2 2009/09/20 2 データの個数 2009/9/21 1 3 2009/09/21 1 2009/9/21 1 2 2009/09/21 1 2 2009/09/21 1 データの個数 2009/9/22 2 4 2009/09/22 2 1 2009/09/22 2 データの個数 6 総合計 と見やすいかも知れない。 第2レベルで 日付 グループ 計数 結合 1 2009/09/20 1 データの個数 2 2009/09/20 2 データの個数 2 2009/09/21 1 データの個数 1 2009/09/22 2 データの個数 6 総合計 ーーーー (2)ピボットテーブル これも知らないのかな。有名で説明略。したこと無ければ、Googleで照会すればたくさん説明が出る。 (1)(2)が早いはず。 ーーー (3)VBA VBAの経験はあるのかな。この手のコントロールブレークによる集計は、昔は仕事で、まずやらされたもので、プログラマの常識だったが。 色々のやり方があるが、簡単なロジックは 日付+グループでソート VBAでデータ最終行を知る。(End(xlup)利用) (1)全データ(最終行までの全行)の個々のデータについて繰り返し(ForNext) (2)比較キーは日付+グループの文字列を作る。以下「キー」ということとすると (3)直前行のキーと、今のキーを比較して、キーが変わるまで、件数を足しこみ(+1する) (4)その行でキーが変わったら件数合計している変数をキーと共に別セル範囲か別シートに書き出し。 今までの件数合計をクリアして、新しいキーで+1し、 直前のキーとして、日付+グループの文字列を作る。 最初行と最終行の処理が少し変える必要があるのでに少し注意が要る。 全体のコードはあえて書かない。勉強のこと。 ーー エクセルのデータメニューの集計の操作も、エクセルでは内部でこのロジックで処理しているのではないかな。前もってソートしないといけない点などが、それをうかがわせる。

tomy01
質問者

補足

imogasiさん ありがとうございます。 今回の目的は、複数ファイルで管理しているテスト結果を、1つのファイルで日毎(週毎)に集計するためにVBAで実現したく質問させていただきました。言葉足らずで申し訳ございません。 VBAでの実現方法についてはアドバイスを頂いた内容でなんとなく想像できました。1つだけ追加で質問です。 ・結果を入力しているファイルはそのままにしたいのですが、日付・グループ(OK,NG等)の列のみ別のワークシートにコピーしてからアドバイスをしていただいた処理をしなくてはならないでしょうか?

  • tom11
  • ベストアンサー率53% (134/251)
回答No.1

VBAでないと駄目ですか。??? エクセルには、ピボットテーブルと言う機能があります。 これだと、エクセルのもともとの機能なので、 早いと思いますよ。簡単だし。

tomy01
質問者

お礼

tom11さん 画像まで添付していただきありがとうございます。 今回の目的は、複数ファイルで管理しているテスト結果を、1つのファイルで日毎(週毎)に集計するためにVBAで実現したく。

関連するQ&A

  • Excel VBA カタカナ セル判定方法

    Excel VBAでA列はカタカナ文字のみ入力したいです。 ボタンを押下する事により、A列でカタカナ以外の文字が入っていたらセルの色を変えたいと思っています。 「アイウエオ」OK 「アイウぇオ」NG 「亜イウエオ」NG 「アイウ_エオ」NG 各セルに入っている文字列を一文字ずつ切り出して判定すればできるような気がしますが、物凄い時間がかかりそうです。これを簡単な方法で実現できないでしょうか?

  • vbaでvlookup

    エクセルのVBAについて。 指定した範囲の中から検索条件に一致したデータを検索し、取り出してくれる関数vlookup をVBAで実現したいのですが、 目標として、エクセルのセル(列)に、値を入力されているとします。 VBAを実行するボタンをクリックすると、、、 その値に対応する文字列(事前に用意)をその値の右のセルに自動で入力させたいです。 このVBAを作ることが目標です。 vbaでvlookupを実現でなくても、それよりも簡単な方法があれば教えていただきたいです。 お手数ですが、よろしくお願いします。

  • エクセルVBA

    お世話になります エクセルのフィルターをかけて列セルの同じ項目を取り出せますが  列セル  フィルターをかけたら 例)1     1    1     2    2    2    2  とか列セルの同じ数字をフィルターを使わずにVBAを使いとりだし、かつ同じ入力した全ての数字の1つだけ取り出し別のセルに貼り付けたいと思っています  例)1が2つ 2が3つあっても1、2を頭の1つだけとりだしたい   取り出すのを1列のみです よい方法があれば教えて下さい

  • エクセルの関数、VBA? に関する質問です

    エクセルの関数、VBA? に関する質問です 添付画像のように、 複数のセルの内容(C列)を一つのセルに改行して 入力する場合(M列)はどのような関数にすればよいのでしょうか。 そもそも関数では実現できないのでしょうか 現状はいったんテキストエディタにコピペした後に 再度それを一つのセルにペーストしています。 何か良い方法があれば、教えて頂けると助かります。 よろしくお願いします。

  • エクセルVBAでセル選択

    エクセル2000でリストを作成し、VBAで編集しようとしています。 A列に入力されているコードの先頭に「’」をつけて文字列とするための関数をB2のセルからA列のデータが入力されている最後のセルの隣までコピーしたいと思っています。 A列の最終セルを取得するVBAは分かったのですが、その値をB列の選択範囲として使用する方法がわかりません。 エクセルVBAは全くの初心者です。 どなたか教えてください!

  • Excelの編集方法について

    標題、質問です。 Excel2013を利用中です。 セル番地指定で、文字列を入力したい事が目的です。 サンプルを添付します。 入力したいセル番地は"$C$6"と予めデータで存在。 入力したい文字列も、「桃太郎」のように。 それぞれ別のセルにデータとして存在するのですが、 ここからの処理についてご教示ください。 なお、当方の環境が、VBA利用NGとなっていますので、 関数構成でお助け下さい。 お手数ですが、どうぞ宜しくお願い致します。

  • VBAで文字列検索の方法

    エクセルで実現したいVBAです。 セル内に入力されている文字列に任意の文字が含まれているかどうかを判定したいのです。 例えば, 「特別値引対応商品」と入力されているセルに 「値引」という文字が含まれているかどうか のチェックをしたいのです。 検索する文字列(上記の場合なら「値引」)は固定でかまわないのですが,どのようにすれば実現できるでしょうか。 関数を探してみたのですが,ないように思います・・・。

  • エクセルの関数、VBA? に関する質問です

    エクセルの関数、VBA? に関する質問です 添付画像を大きく変更しました。 添付画像のように、 複数のセルの内容(C列)を一つのセルに改行して 入力する場合(M列)はどのような関数にすればよいのでしょうか。 そもそも関数では実現できないのでしょうか 現状はいったんテキストエディタにコピペした後に 再度それを一つのセルにペーストしています。 何か良い方法があれば、教えて頂けると助かります。 よろしくお願いします。

  • VBAでPPTからEXCELにデータをコピー

    こんにちは、ANIMと申します。 EXCELのVBAで下記を実現したいのですが、方法がわかりません。 ご存知の方、どうかご支援よろしくお願いします。 ・POWERPOINTの表のデータをEXCELのセルに貼り付けたい。 ⇒表のデータを手作業でコピーして、EXCELに貼り付ければよいのですが、   PPTのファイルが大量にありVBAで対応したいです。 ・POWERPOINTの表のデータをEXCEL VBAで取り込む方法がわかりません。  (TEXTのデータではなく、表の中のデータの取り込み方です) ・POWERPOINTの表の形式は同じ(例えば、3行5列の表)です。

  • 【VBA】データが途切れた回数をカウントする方法

    添付画像のような1行ごとにデータが入力されている表があります。 このデータには、データが入力されているセルと空白セル(黄色のセル)があります。 1行ごとに、最初にデータが入力されたセルから最後にデータが入力されたセルまでの間に、空白が発生した回数が何回あるのかをカウントしたいと思っております。 空白セルの数をカウントするのではなく、データが途切れた回数をカウントしたいのです。 VBAを使って、上記のような処理は可能でしょうか? 私は現在VBAを勉強中で知識が浅いため分かりませんでした。 もし可能であれば、その方法を教えていただけると大変助かります。 お手数お掛けいたしますが、よろしくお願い致します。