ExcelVBAでの検索結果抽出方法

このQ&Aのポイント
  • ExcelVBAを使用して、大量の表データから特定の条件に合致するデータを抽出する方法について教えてください。
  • 具体的には、地域別の表を作成し、男女別、スポーツ別に人数をまとめたいと考えています。
  • さらに、年代が空白の場合もあり、それらのデータも取り扱いたいです。
回答を見る
  • ベストアンサー

ExcelVBAでの検索結果抽出方法

ExcelVBAで教えて下さい。 A | B | C | D | E |F| 地域コード| 性別コード|年代|野球|サッカー|テニス| 201| 1 | 40 | 5 | - | 1| 201| 2 | 55 | 6 | 1 | 3| というような表が1万行近くあります。 これを「地域別の表」にして、なおかつ「男女別」「スポーツ別」にして、人数を表にしたいと思っています。 表のイメージはこんな感じです。 ーー| 201 | 野球|サッカー|テニス| 男性| 40 | 5 | - | 1 | … 女性| 55 | 6 | 1 | 3 | 年代は40、45と5才刻みで100歳までで、男女は1と2のコードで表します。 クロスのところにはいっているのは人数です。 Sheet1が元データなので、Sheet2に表を作りたいです。表はどうにか作れるので、 ・地域コード ・性別コード ・スポーツ に、一致した場合に別シートにコピーできるコードを教えていただけるとありがたいです。 Sheet1の元データの年代は、地域によっては、該当なしだと無い年代もあります。 今回は投稿のためわかりやすければ…と思い、空白セルにハイフンを入れましたが実際は入っていません。 ややこしくて申し訳ありませんが助けていただきたく、お願い致します。

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

  • ベストアンサー
  • tom04
  • ベストアンサー率49% (2537/5117)
回答No.2

こんばんは! 一例です。 ↓の画像で左側がSheet1で右側がSheet2とします。 尚、Sheet3を作業用のSheetとして使用していますので、Sheet3は全く使用していない状態にしておいてください。 標準モジュールです。 Sub Sample1() Dim i As Long, cnt As Long, endRow As Long, wS1 As Worksheet, wS2 As Worksheet, wS3 As Worksheet Set wS1 = Worksheets("Sheet1") Set wS2 = Worksheets("Sheet2") Set wS3 = Worksheets("Sheet3") Application.ScreenUpdating = False wS2.Cells.ClearContents wS1.Range("A:A").AdvancedFilter Action:=xlFilterInPlace, unique:=True wS1.Range("A:A").Copy wS3.Range("A1") wS3.Range("A:A").Sort key1:=wS3.Range("A1"), order1:=xlAscending, Header:=xlYes wS1.ShowAllData For i = 2 To wS3.Cells(Rows.Count, "A").End(xlUp).Row wS1.Range("A1").CurrentRegion.AutoFilter field:=1, Criteria1:=wS3.Cells(i, "A") wS1.Range("B:F").Copy wS3.Range("B1") endRow = wS3.Cells(Rows.Count, "B").End(xlUp).Row Range(wS3.Cells(1, "B"), wS3.Cells(endRow, "F")).Sort key1:=wS3.Range("B1"), order1:=xlAscending, Header:=xlYes, _ key2:=wS3.Range("C1"), order1:=xlAscending, Header:=xlYes wS3.Range("B1") = wS3.Cells(i, "A") endRow = wS3.Cells(Rows.Count, "B").End(xlUp).Row If wS2.Cells(Rows.Count, "A").End(xlUp).Row > 1 Then cnt = wS2.Cells(Rows.Count, "A").End(xlUp).Row + 1 Else cnt = 1 End If Range(wS3.Cells(1, "B"), wS3.Cells(endRow, "F")).Copy wS2.Cells(cnt, "A") Next i With wS2.Range("A:A") .Replace what:=1, replacement:="男性", lookat:=xlWhole .Replace what:=2, replacement:="女性", lookat:=xlWhole End With wS1.AutoFilterMode = False wS3.Cells.Clear Application.ScreenUpdating = True MsgBox "処理完了" End Sub こんな感じではどうでしょうか?m(_ _)m

minminwamidori
質問者

お礼

理想に近い形ができました!ありがとうございました!

その他の回答 (1)

回答No.1

VBAでということなのですが、VBAで作ったユーザー定義関数によって解決してはと考えます。データベースのシートは変更することなく行うようにと考えたとき、既存のVlookUP関数では重複したデータ(2件目以降)を拾い上げられません。累積して検索拾い上げを行う方法を書いておきます。 (1)まず、検索にかけたものがデータベース上のどこに、何件あるのかを知る必要があります。この際、ヒットした位置を一度カンマ区切りのデータとして単一セルに書き出しておくことをお勧めします。これ以外の方法でもユーザー定義関数で作ってはありますが、件数がかさむと処理が重くなるので上記の方法で書き出したほうがいいとおもいます。 ----該当するデータの位置をカンマ区切りで書き出すユーザー定義関数AcuMatch----下記をVBAのモジュールにコピペして使ってください。 Function AcuMatch(条件 As Variant, 検索範囲 As Range) As Variant Application.Volatile Dim tmpans As Integer 'CountIf関数によって一つずつ検索し、存在すれば 1,しなければ 0 Dim SR As Integer '始まりの行番地 Dim ER As Integer '終わりの行番地 Dim SC As Integer '始まりの列番地 Dim EC As Integer '終わりの列番地 Dim i As Integer 'カウンタ Dim tmpmemo As Variant Dim Acutemp As String '検索範囲のシート名、ブック名を格納 S = 検索範囲.Parent.Name w = 検索範囲.Parent.Parent.Name '初期化 tmpans = 0 SR = 0 Coun = 1 tmpmemo = "" Acutemp = "" '範囲のR1C1化 SR = 検索範囲.Row SC = 検索範囲.Column ER = 検索範囲.Row + 検索範囲.Rows.Count - 1 EC = 検索範囲.Column + 検索範囲.Columns.Count - 1 '処理 If SR = ER Then '行が1の場合(水平方向に検索) For i = SC To EC Step 1 tmpans = WorksheetFunction.CountIf(Workbooks(w).Sheets(S).Cells(SR, i), 条件) If tmpans = 1 Then tmpmemo = i - SC + 1 Strtemp = Mid(Str(tmpmemo), 2, 10) Acutemp = Acutemp & "," & Strtemp 'Coun = Coun + 1 End If Next i mojisuu = Len(Acutemp) AcuMatch = Mid(Acutemp, 2, mojisuu) Else 'レコード検索(垂直方向に検索) For i = SR To ER Step 1 tmpans = WorksheetFunction.CountIf(Workbooks(w).Sheets(S).Cells(i, SC), 条件) If tmpans = 1 Then tmpmemo = i - SR + 1 Strtemp = Mid(Str(tmpmemo), 2, 10) Acutemp = Acutemp & "," & Strtemp 'Coun = Coun + 1 End If Next i mojisuu = Len(Acutemp) AcuMatch = Mid(Acutemp, 2, mojisuu) End If End Function (2)書き出された検索位置を表すカンマ区切りデータを元にして拾い上げる。 ----カンマ区切りテキストから配列として読み込み検索するユーザー定義関数CSVVLookup---- Function CSVVLookUP(banme As Double, strArray As String, 対象範囲 As Range, Optional 対象列 As Integer = 1, Optional エラー除去 As Boolean = True) As VariantDim tmp As Variant tmp = Split(strArray, ",") Dim part As Variant Dim result() As Single ReDim result(UBound(tmp)) Dim cnt As Integer cnt = 0 For Each part In tmp result(cnt) = Val(part) cnt = cnt + 1 Next If エラー除去 = True And cnt < banme Then CSVVLookUP = "" Else CSVVLookUP = WorksheetFunction.Index(対象範囲, WorksheetFunction.Index(result, banme), 対象列) End If End Function この二つの関数を使ってやってみてはと思います。 詳しくは http://hirorinmattsu.com/

参考URL:
http://hirorinmattsu.com/

関連するQ&A

  • ExcelVBAのコピーもしくは集計方法

    ExcelVBAについて質問させて下さい。 いくつもの区分に分かれたデータが以下のように並んでいます。(区分は80程度あります) A   | B | C | D | E | F | G | H | ------------------------------------------- 1 | 行ラベル | 11 | 12 | 13 | 14 | 15 | 21 | 22 | ------------------------------------------- 2 | 123456 | | | | | | | | ------------------------------------------- 3 |(性別:男)1| | | | | | | | ------------------------------------------- 4 | (年代)40 | 1 | 5 | | | | | | ------------------------------------------- 5 | (年代)45 | | | | 2 | | | | ------------------------------------------- 6 | (年代)50 | ------------------------------------------- … 16| (年代)100| 1 | 2 | 3 | 2 | 1 | | | ------------------------------------------- 17|(性別:女)2| ------------------------------------------- 18|(年代)40 | ------------------------------------------- … 30|(年代)100| ------------------------------------------- 31| 234567 | ------------------------------------------- 32|(性別:男)1| ------------------------------------------- 33| (年代)40| … ・「123456」「234567」は区分コードです。 ・( )を含めた文字は、実際の表にはありません。 ・区分ごとに「男」と「女」があり、それぞれ「40」から5才刻みで「100」まで年代があります。 ・行ラベル「11」「12」はあるデータ名を数値化したものです。  (1)区分コード  (2)性別  (3)行ラベル  (4)年代 以上の4つの条件が集約された表です。 ・この表は別にデータがあったのではなく、これを与えられました。マクロなどで加工していません。 ・年代は数値が入っていない場合には、行が無い場合があります。40代は何も数値がないので、45から始まるなど。 この表を使って何をしたいかというと、行ラベルの「12」「13」「14」「15」だけに絞り別シートに抽出し、区分コード別に表を作りたいのです。表を作成するときには、抜けている年代もきちんと入れて。例え値が0でも。 以前、ここでの質問で複数条件で一致した場合の集計方法を教えていただきましたので、A列をコピーして、「区分コード」「性別コード」を次のコードが出てくるまでコピーできれば同じことができると考えました。 ですが、次のコードが出てくるまでのコピーのコードの記述方法、列をコピーするので区分コードの行では、性別コードの部分もコピーして上書きしてしまう方法が分かりませんでした。 一番は、こんなややこしい表の集計方法を教えていただけましたら幸いですが、もしくは、次の値が出てくるまで同じもののコピーの繰り返しと特定の文字は無視して上書きの方法を教えて下さい。 例えばなのですが、「123456」がある列に対して、「1を空白にする」という置換を行ったら「23456」になってしまいますか? 質問が多くて申し訳ございません。

  • ExcelVBAで複数条件で抽出して表を作成

    ExcelVBAで複数条件一致の時の抽出法方を教えて下さい。 ここで教えていただいたコードがあるのですが、質問の仕方が悪かったのか、意図した結果が得られず、改変もできなかったので再質問です。よろしくお願い致します。 質問をすることは会社の許諾を得ているのですが、会社のPCからは制限がかかっており投稿できないのでスマホからです。なるべく伝わりやすいよう努めますが、力不足なときはお許し下さい。 Excelのオートフィルタ機能でもよいとも思ったのですが、処理数が100を越えるため、VBAを検討することにしました。 (1)処理前の並び順と、VBAで処理した後の並び順は異なります。 処理前:コードの昇順 処理後:地域ごとに表を作成し、更に広域ごとに表を掲載するシートを分ける (2)処理前の表は数字しか並んでいません。全てコード化しています。 (3)処理前はいくつもの地域の男女の値が表になっていますが、 ・地域コード ・性別コード ・年代コード ・疾患コード で抽出して、表を作る方法を教えて下さい。1つの地域を抽出する方法で良いのでお願い致します。 後は表を配置する場所と地域コードを指定して、自力で頑張ります。 <元データ> ---|-A-|-B-|-C-|-D-|-E-|-F-|-G-| 列|地域| 性 | 年 | 21 | 22 | 23| 24 | 01| 201 | 1 | 40 | 1 | 2 | 3 | 4 | 02| 201 | 1 | 50 | 2 | 4 | 2 | 1 | 03| 201 | 1 | 55 | 3 | 0 | 0 | 7 | 04| 201 | 1 | 65 | 2 | 1 | 1 | 6 | 05| 201 | 1 | 80 | 1 | 2 | 4 | 1 | 06| 201 | 1 | 95 | 7 | 5 | 4 | 3 | 07| 201 | 2 | 45 | 0 | 3 | 3 | 0 | 08| 201 | 2 | 60 | 4 | 2 | 2 | 6 | 09| 201 | 2 | 70 | 1 | 2 | 3 | 4 | 10| 201 | 2 | 75 | 3 | 6 | 0 | 3 | 11| 201 | 2 | 85 | 5 | 2 | 4 | 2 | 12| 201 | 2 |100| 2 | 2 | 1 | 0 | 13| 202 | 1 | 40 | 1 | 2 | 3 | 4 | 14| 202 | 1 | 45 | 3 | 5 | 2 | 7 | 15| 202 | 1 | 55 | 1 | 2 | 3 | 2 | …続く ・A列は地域コードです。 ・B列は性別コードです。男性が「1」女性が「2」です。 ・C列は年代コードです。 40/45/50/55/60/65/70/75/80/85/90/95/100 という形に40から100まで5歳刻みです。 ・D列~G列は疾病コードです。 <希望> ・元データの年代は値がないと表示がありません。ですが、出力される表には全ての年代を表示させるのが希望です。 <処理後の表> VBA実行後は、以下のような表が1つ作成できることが希望です。教えていただいたコードを元に、配置場所を変更できるようになっていると大変ありがたいです。 01| 201 |----| 21 | 22 | 23 | 24 |合計| 02|男性 | 40 | 1 | 2 | 3 | 4 | 10 | 03|男性 | 45 |-----|-----|-----|----| 0 | 04|男性 | 50 | 2 | 4 | 2 | 1 | 9 | 05|男性 | 55 | 3 | 0 | 0 | 7 | 10 | 06|男性 | 60 |-----|-----|-----|----| 0 | 07|男性 | 65 | 2 | 1 | 1 | 6 | 10 | 08|男性 | 70 |-----|-----|-----|----| 0 | 09|男性 | 75 |-----|-----|-----|----| 0 | 10|男性 | 80 | 1 | 2 | 4 | 1 | 8 | 11|男性 | 85 |-----|-----|-----|----| 0 | 12|男性 | 90 |-----|-----|-----|----| 0 | 13|男性 | 95 | 7 | 5 | 4 | 3 | 19 | 14|男性 |100|-----|-----|-----|----| 0 | 15|男性 |合計| 16 | 14 | 14 | 22| 66 | 16|女性 | 40 |-----|-----|-----|----| 0 | 17|女性 | 45 | 0 | 3 | 3 | 0 | 6 | 18|女性 | 50 |-----|-----|-----|-----| 0 | 19|女性 | 55 |-----|-----|-----|-----| 0 | 20|女性 | 60 | 4 | 2 | 2 | 6 | 14 | 21|女性 | 65 |-----|-----|-----|-----| 0 | 22|女性 | 70 | 1 | 2 | 3 | 4 | 10 | 23|女性 | 75 | 3 | 6 | 0 | 3 | 12 | 24|女性 | 80 |-----|-----|-----|-----| 0 | 25|女性 | 85 | 5 | 2 | 4 | 2 | 13 | 26|女性 | 90 |-----|-----|-----|-----| 0 | 27|女性 | 95 |-----|-----|-----|-----| 0 | 28|女性 |100| 2 | 2 | 1 | 0 | 5 | 29|女性 |合計| 15 | 17 | 13 | 15 | 60 | こんな表にしたいです。 縦横のそれぞれの合計が出せると素敵です。 お知恵を拝借したく、何卒、よろしくお願い致します。

  • ExcelVBA表の見出しを付ける方法について

    ExcelVBAで複数の表に、同じ見出し行を入れる方法を教えて下さい。 ExcelのSheet1に数字だけで構成された表があります。それぞれ意味があり、例えば「4列は市町村コード」「5列は性別」「17列は年齢」「20列は疾病コード」という感じです。 VBAで市町村・男女別で、年齢と疾病コードに一致した場合にカウントする場合の表は回答をいただき作成できました。 ですが50以上×男女分の表を作るのに疾病コードを  Range("C3,C136").Value = 14500  Range("D3,D136").Value = 14510 と、していると、入力間違えも発生しかねないですし、きりがなく、他に良い方法があればご教授いただけましたらと思います。 疾病コードの数字は連番ではないためコピーができません。 疾病コードは「132」あります。 よろしくお願い致します。

  • 3つの条件に合致した数値を抽出させたいです。

    Excel2007で添付画像の左側の様に、 エリア別、性別、年代別の人数表を1つのシートで DBとして用意しています。 別シートで添付画像の右側の様に枠を用意しており、 地域の欄でプルダウンのリストから選んだ地域に 応じて、会員数の空欄セルが自動で抽出される様に したいです。 IndexやMatchやSUMPRODUCTで試してみているのですが、 1つ目のセルだけ、うまく抽出されて来るのですが、 2つ目のセル以下の値が、すべて「#N/A」となってしまい 困っています。 どなたか解決策を教えて頂けないでしょうか。

  • ExcelVBA複数条件一致後別シートに結果表示

    初めて質問させていただきます。VBAとマクロを勉強中なのですが、数値だけのcsvデータ(3万行くらい)をマクロで処理するように指示されて困っています。 ●ファイルの内容(概要) <Sheet1> A列:性別(男性:1、女性:2でコード化) B列:死因コード(数値5~6桁) C列:年齢 D列:市町村(3桁でコード化「201」等) <Sheet2> ・「セルA1」に表にしたい市町村コードをあらかじめ入力しておく ・セルB1~セルEC1まで死因コード ・セルA2~セルA132まで年齢0~130 ・セル範囲B2~EC132に市町村1の男性の値が入る ・セルB133~セルEC133まで死因コード ・セルA134~A264まで年齢0~130 ・セル範囲B134~EC264に市町村1の女性の値が入る Sheet2にはあらかじめ表を作成しておき、行と列の値を参照してSheet1で一致する値が、列と行が交わるところの空白セルに入力した市町村コードと一致していることもふるいにかけられ、表で結果としてカウントされるときには男女別に分かれるようにしたいのですが可能でしょうか? ややこしくて申し訳ありません。繰り返しあらかじめ作成された表にカウント結果を入力させる記述はヒントを頂ければ頑張ります。 なので、4つの条件に一致した場合にカウントして別シートに返すにはどうしたらいいのか助けていただけますと幸いです。 それと、シート1の最終行は決まっていません。

  • Excelで名前にコードをつける方法

    Excelで例えばサッカーを01、バスケ 02、テニス 03、水泳 04、野球 05のようにスポーツ名を入力すると、コードが出てくるようにしたいのですが方法が判らなくて困っています。できるだけ判りやすい説明でお願いします。 スポーツ名に該当する部分が500種類くらいあります。 また名前OO、好きなスポーツ△△の人にコードをつけるというような感じで使いたいです。 よろしくお願いします。

  • Excel計算式を教えてください

    添付の様な100人の元データSheet1(氏名、年齢、性別)から、Sheet2の30歳代~90歳代の年齢層別の男女の人数をExcelの計算式で求めたいのですが、残念ながら私の能力ではどんな式を使ったら良いのかわかりません。 識者の皆さん、教えてくださいませんか?

  • 複数の検索値から任意のデータを抽出する方法

    Excelの質問です。 Sheet1には、1行1件のコード、地域、金額の表があります。 A列のコードは、同じコードはひとかたまりになっていますが、 同じコードが2行ある場合や、1行またはそれ以上ある場合と決まっていません(最大6行)。 また、コードの順も昇順・降順になっていません。 Sheet2には、A列にコードだけが入力してあり、コードをキーにして、 Sheet1から地域と金額を自動表示したいのですが、 MATCHやINDEX関数を組み合わせたりしたのですが、うまくいきません。 関数式をお教えください。 <Sheet1> A B C →列番号です。 コード 地域 金額 56789 東京 100 56789 大阪 50 12345 大阪 400 12345 神奈川 200 12345 東京 1000 22222 大阪 300 22222 神奈川 400 22222 東京 100 ・・・・・つづく <Sheet2> A B C 12345 大阪 400 →B列とC列を数式で自動表示したい 神奈川 200 東京 1000 56789 東京 100 大阪 50 22222 ・・・・・つづく

  • エクセル 検索したデータを1行抽出するには

    よろしくお願いします。 シート1には 氏名       生年月日   コード    コード   コード    交付番号 安心太郎    S20.12.20    1      2      3     1234567890 安全花子    S40.11.11    1                   2345678901 道路一郎    S30.10.25    2      3            3456789012 橋川理恵    S25.12.17    3                   4567890123 天気良太    S50.11.28    1      3            5678901234 という具合に、社員一覧表があるとします。 そして、シート2には コード番号     名前   1       普通自動車免許   2       原動機付自転車免許   3       大型自動車免許 というようにコード一覧表があるとします。 ここからなのですが、 シート3には「1.普通自動車免許取得者一覧」 シート4には「2.原動機付自転車免許取得者一覧」 シート5には「3.大型自動車免許取得者一覧」 というように、シート1にデータ入力をしたら、 自動的に、コード別に検索して、該当するコードに引っかかる者は、それぞれのコード別シート(シート3~5)に、該当者のデータ1行分(氏名・生年月日・コード・交付番号等)が丸々コピー(転記)されるにはどうしたらよろしいのでしょうか。 関数等を調べましたが、該当するものが見あたらず、 やはり、マクロで行う方法なのかと思ったのですが、 マクロが超初心者のため、やり方や命令文(?)などが全くわからず、困っております。 よろしくおねがいいたします。

  • ExcelVBAで一定ルールでの行追加

    いつもお世話になっています。 ExcelVBAについて教えて下さい。 以下のような表があったとします。 --|--A--|--B----|--C--|--D--|--E--| -||-性別-|-年代-|-数1-|-数2-|-数3-| 1|---1--|--40--|---5--|--0--|--3--| 2|---1--|--55--|---0--|--1--|--0--| 3|---1--|--60--|---2--|--1--|--0--| 4|---1--|--70--|---3--|--0--|--2--| 5|---1--|--90--|---0--|--1--|--1--| 6|---1--|-100--|---1--|--1--|--0--| 7|---2--|--45--|---4--|--2--|--1--| 8|---2--|--50--|---0--|--3--|--5--| 性別はコード別で、年代は40から100までが5才刻みですが、数(集計された結果)が無い年代は行がありません。 表は元々与えられた物なのですが別に使用するので、数が無くてもすべての年代が入っている表に作り替えたいと思っています。縦横の合計値も同時に出すのと、こういった表を100近く処理しないといけないので、表ごとに抜けている年代を確認して挿入…というのは手間がかかり、また複数のファイルを処理するのでVBAでやった方がよいと思いましたが、自分で書いてみてもうまくいきませんでした。 実現させたい形は以下の通りです。 ・男性  40/45/50/55/60/65/70/75/80/85/90/95/100  ・男性の40から100までの年代ができたら、  100の下に男性の数(縦)の合計値  ・男性の合計の下に、男性と同様に女性  ・女性の100の下に女性の合計値  ・数3の横列に1列追加して、年代別合計と男性と女性の総数 以上なのですが、お助けいただけますと幸いです。 よろしくお願い致します。

専門家に質問してみよう