- ベストアンサー
ExcelVBAで複数条件で抽出して表を作成する方法
- ExcelVBAを使用して複数の条件に一致するデータを抽出し、表を作成する方法を教えてください。
- 処理前のデータの並び順と処理後の並び順が異なります。処理後は地域ごとに表を作成し、広域ごとにシートを分けます。
- 処理前のデータには地域コード、性別コード、年代コード、疾患コードがあります。これらの条件で抽出し、表を作成する方法を教えてください。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
やりたい事と少し方向性が違うかもしれませんが、PivotTableを使ったアプローチ。 1)ActiveWorkbookに対して処理を行う。 2)ActiveWorkbookに「元データ」という名前のシートがあり、データはそのA1セルが起点。 3)A列は空白セルがない連続データであり、データ行数をA列の個数で判断できる。 4)1行目は空白セルがない連続データであり、データ列数を1行目の個数で判断できる。 5)A1:C1セルに "地域","性","年" という項目名がある。 以上を前提条件とします。 Sub Macro1() Dim pt As PivotTable Dim i As Long With ActiveWorkbook .Names.Add Name:="database", RefersToR1C1:="=INDEX(元データ!R1,COUNTA(元データ!R1)):INDEX(元データ!C1,COUNTA(元データ!C1))" Set pt = .PivotCaches.Add(SourceType:=xlDatabase, SourceData:="database").CreatePivotTable("") End With pt.AddFields RowFields:=Array("性", "年"), ColumnFields:="データ", PageFields:="地域" For i = 4 To Range("database").Columns.Count pt.AddDataField pt.PivotFields(i), , xlSum Next With pt.PivotFields("性") .PivotItems("1").Caption = "男性" .PivotItems("2").Caption = "女性" .ShowAllItems = True End With pt.PivotFields("年").ShowAllItems = True End Sub
その他の回答 (3)
- tom04
- ベストアンサー率49% (2537/5117)
No.1.2です。 たびたびごめんなさい。 各地域ごとで男女別の合計が必要なのですね! 前回は単に総合計だけでしたので、無視して↓のコードにしてください。 今回もSheet3を作業用のSheetとして使用しています。 Sheet1のデータは2行目以降にあるとします。 Sub Sample2() Dim i As Long, j As Long, k As Long, endRow As Long Dim c As Range, myRange As Range, wS1 As Worksheet, wS2 As Worksheet Set wS1 = Worksheets("Sheet1") Set wS2 = Worksheets("Sheet2") Application.ScreenUpdating = False endRow = wS1.Cells(Rows.Count, "A").End(xlUp).Row wS2.Cells.Clear With Worksheets("Sheet3") wS1.Range("A:A").AdvancedFilter Action:=xlFilterInPlace, unique:=True wS1.Range("A:A").SpecialCells(xlCellTypeVisible).Copy .Range("A1") wS1.ShowAllData wS1.Range("B1").Resize(, 6).Copy .Range("C1") .Range("I1") = "合計" .Range("A1").Sort key1:=.Range("A1"), order1:=xlAscending, Header:=xlYes For k = 2 To 14 .Cells(k, "B") = (k - 2) * 5 + 40 Next k .Cells(15, "D") = "合計" Set myRange = .Range("C2:H14") For i = 2 To .Cells(Rows.Count, "A").End(xlUp).Row .Range("C1") = .Cells(i, "A") wS1.Range("A1").AutoFilter field:=1, Criteria1:=.Cells(i, "A") wS1.Range("A1").AutoFilter field:=2, Criteria1:="1" .Range("C15") = .Cells(i, "A") & "男性" Range(wS1.Cells(1, "A"), wS1.Cells(endRow, "G")).SpecialCells(xlCellTypeVisible).Copy .Range("J1") For k = 2 To 14 Set c = .Range("L:L").Find(what:=.Cells(k, "B"), LookIn:=xlValues, lookat:=xlWhole) If Not c Is Nothing Then .Cells(c.Row, "K").Resize(, 6).Copy .Cells(k, "C") Else .Cells(k, "C") = 1 .Cells(k, "D") = .Cells(k, "B") End If Next k With .Range("I2:I14") .Formula = "=SUM(E2:H2)" .Value = .Value End With With .Range("E15:I15") .Formula = "=SUM(E2:E14)" .Value = .Value End With .Range("C1:I15").Copy wS2.Cells(Rows.Count, "A").End(xlUp).Offset(1) .Range("J1:P14").ClearContents myRange.ClearContents wS1.Range("A1").AutoFilter field:=1, Criteria1:=.Cells(i, "A") wS1.Range("A1").AutoFilter field:=2, Criteria1:="2" .Range("C15") = .Cells(i, "A") & "女性" Range(wS1.Cells(1, "A"), wS1.Cells(endRow, "G")).SpecialCells(xlCellTypeVisible).Copy .Range("J1") For k = 2 To 14 Set c = .Range("L:L").Find(what:=.Cells(k, "B"), LookIn:=xlValues, lookat:=xlWhole) If Not c Is Nothing Then .Cells(c.Row, "K").Resize(, 6).Copy .Cells(k, "C") Else .Cells(k, "C") = 2 .Cells(k, "D") = .Cells(k, "B") End If Next k With .Range("I2:I14") .Formula = "=SUM(E2:H2)" .Value = .Value End With With .Range("E15:I15") .Formula = "=SUM(E2:E14)" .Value = .Value End With .Range("C2:I15").Copy wS2.Cells(Rows.Count, "A").End(xlUp).Offset(1) .Range("J1:P14").ClearContents myRange.ClearContents Next i wS1.AutoFilterMode = False .Cells.Clear End With With wS2.Range("A:A") .Replace what:=1, replacement:="男性", lookat:=xlWhole .Replace what:=2, replacement:="女性", lookat:=xlWhole End With With wS2 .Rows(1).Delete .Range("A1").CurrentRegion.Borders.LineStyle = xlContinuous .Columns.AutoFit End With Application.ScreenUpdating = True wS2.Select MsgBox "処理完了" End Sub ※ すべての地域を羅列するようにしていますので、 時間を要すると思います。m(_ _)m
お礼
ありがとうございます。せっかく書いていただきましたが、表しか作成されませんでした(;_;)それと、表を羅列したいのではなく、地域コードを指定して1つだけ表を作りたいのです。総数を出したいのは書いていただいたとおり希望ですが、それはどうにかなるので、1つの地域コードを指定して表を出力するにはどうしたらいいのか教えて下さい_(._.)_
- tom04
- ベストアンサー率49% (2537/5117)
続けて・・・後半部分です。 wS3.Range("B1:H14").Copy wS2.Cells(Rows.Count, "A").End(xlUp).Offset(1) myRange.ClearContents wS3.Range("I:O").Clear .AutoFilter field:=2, Criteria1:=2 endRow = wS1.Cells(Rows.Count, "A").End(xlUp).Row Range(wS1.Cells(1, "A"), wS1.Cells(endRow, "G")).Copy wS3.Range("I1") For k = 2 To 14 Set c = wS3.Range("K:K").Find(what:=wS3.Cells(k, "A"), LookIn:=xlValues, lookat:=xlWhole) If Not c Is Nothing Then wS3.Cells(c.Row, "J").Resize(, 6).Copy wS3.Cells(k, "B") Else With wS3.Cells(k, "B") .Value = 2 .Offset(, 1) = wS3.Cells(k, "A") End With End If Next k With wS3.Range("H2").Resize(13) .Formula = "=SUM(D2:G2)" .Value = .Value End With wS3.Range("B2:H14").Copy wS2.Cells(Rows.Count, "A").End(xlUp).Offset(1) myRange.ClearContents wS3.Range("I:O").Clear End With Next i wS1.AutoFilterMode = False wS3.Cells.Clear With wS2 .Rows(1).Delete endRow = .Cells(Rows.Count, "A").End(xlUp).Row .Cells(endRow, "A").Offset(1) = "合計" Set c = Range(.Cells(1, "A"), .Cells(endRow, "A")) For k = 3 To 7 Set myRange = Range(.Cells(1, k), .Cells(endRow, k)) .Cells(endRow + 1, k) = WorksheetFunction.SumIf(c, 1, myRange) + _ WorksheetFunction.SumIf(c, 2, myRange) Next k .Range("A1").CurrentRegion.Borders.LineStyle = xlContinuous .Range("A:A").Replace what:=1, replacement:="男性", lookat:=xlWhole .Range("A:A").Replace what:=2, replacement:="女性", lookat:=xlWhole End With Application.ScreenUpdating = True wS2.Select MsgBox "処理完了" End Sub じっくり考えればもっと簡単になるかもしれませんが、 とりあえずはこの程度で・・・m(_ _)m
お礼
ありがとうございます。試してみたのですが、表はきれいにできるのですが、結果は抽出されませんでした。それと、表は地域コード1つだけで作りたいので、羅列はしなくてよいのです。説明が下手で申し訳ありません_(._.)_1つだけで出力するにはどうしたらよいか、教えていただけますと幸いです。
- tom04
- ベストアンサー率49% (2537/5117)
こんばんは! Sheet1のデータをSheet2に表示するようにしています。、 Sheet見出し上には3つSheetがあり、Sheet3は使用していない状態にしておいてください。 Sheet1は1行目が項目行でデータは2行目以降にあるとします。 ↓のコードを標準モジュールにコピー&ペーストしてマクロを実行してみてください。 ただ、ダラダラと長いコードになってしまいましたので、 2回に分けて投稿します。 まず前半部分 Sub Sample1() Dim i As Long, k As Long, endRow As Long Dim c As Range, myRange As Range Dim 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.Clear wS1.Range("B1").Resize(, 6).Copy wS3.Range("B1") wS3.Range("H1") = "合計" For i = 2 To 14 wS3.Cells(i, "A") = 40 + (i - 2) * 5 Next i Set myRange = wS3.Range("B2:H14") wS1.Range("A:A").AdvancedFilter Action:=xlFilterInPlace, unique:=True endRow = wS1.Cells(Rows.Count, "A").End(xlUp).Row Range(wS1.Cells(2, "A"), wS1.Cells(endRow, "A")).Copy wS3.Range("A16") wS1.ShowAllData For i = 16 To wS3.Cells(Rows.Count, "A").End(xlUp).Row wS3.Range("B1") = wS3.Cells(i, "A") With wS1.Range("A1") .AutoFilter field:=1, Criteria1:=wS3.Cells(i, "A") .AutoFilter field:=2, Criteria1:=1 endRow = wS1.Cells(Rows.Count, "A").End(xlUp).Row Range(wS1.Cells(1, "A"), wS1.Cells(endRow, "G")).Copy wS3.Range("I1") For k = 2 To 14 Set c = wS3.Range("K:K").Find(what:=wS3.Cells(k, "A"), LookIn:=xlValues, lookat:=xlWhole) If Not c Is Nothing Then wS3.Cells(c.Row, "J").Resize(, 6).Copy wS3.Cells(k, "B") Else With wS3.Cells(k, "B") .Value = 1 .Offset(, 1) = wS3.Cells(k, "A") End With End If Next k With wS3.Range("H2").Resize(13) .Formula = "=SUM(D2:G2)" .Value = .Value End With
お礼
地域コードが選択できることに気づきませんでした(^_^;)スミマセン…ちょっと手間ですが、形式を指定して貼付で「値だけ」にして地道に表をレイアウトしていきたいと思います。ちょっと急ぎなので、この回答が今の私に一番良さそうです。発想の転換でした!ありがとうございました!
補足
ありがとうございます。ですが、全ての合計を出したいのではなく、1つの地域コードを指定して、表を作成したいのです。ピポットテーブルは検討しましたが、100近くある地域コードについてそれぞれやるのには不向きと思い止めた経緯があります。