[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『データ抽出の方法』(蒔禁稽洌)
データの抽出方法を自動で できないものかと思案しています。
データとしては下記のような表から抽出したいと考えています。
下記の表を シート1 とします
A B C D 1 3月1日 お菓子 チョコ 2個 2 3月3日 野菜 にんじん 3個 3 3月5日 お菓子 飴 5個 4 3月6日 日用品 シャンプー 1本 5 3月10日 野菜 キャベツ 3個
この表から B列の同じ項目名 たとえば お菓子で
シート2に お菓子のみの表でまとめたいと考えています。(自動)
もし やり方をご存知のかたおられましたら 教えてください。
< 使用 Excel:Excel2013、使用 OS:Windows7 >
>(自動)
同シートでいいなら1行目見出しつけて、オートフィルタ。でいいんでないの? (GobGob) 2016/03/21(月) 15:33
衝突
まず 1行目に列見出しを挿入して、あとはオートフィルタでは? >データの抽出方法を自動で ここは詳しく、何をどうしたときにとか説明しないと... そこのところは、自分で考えましょう。 (seiya) 2016/03/21(月) 15:35
皆さんからも指摘がありますが、【自動】というのは、【どこまで自動】ということを想定しておられますか?
腕を組んで頭の中で『お菓子』といってみても、パソコンは認識できません。 "お菓子" というのを 何かの方法でパソコンに伝えるわけですよね。
簡単な方法の1つがオートフィルターですね。 ただ、シート1 から シート2 へ抜き出す ということでしょうから、抽出されたものをコピーして シート2 にペーストするという操作が必要になりますが。
コピペ操作がはいるのはは、自動じゃないからいやだということであればフィルターオプション(フィルター詳細設定)があります。 この機能を使えば、コピペなしで、シート1から抽出してシート2にセットすることが可能です。
(β) 2016/03/21(月) 16:11
データ入力シート1があり シート1に日々データを入力します。
(日々 結構な量のデータを入力します。)
別シート(シート2)に B列の項目名別で 抽出された データとしてまとめたいのです。
A B C D E F G H 1 3月1日 お菓子 チョコ 2個 3月3日 野菜 にんじん 3個 2 3月5日 お菓子 飴 5個 3月10日 野菜 キャベツ 3個 4 5
上記のようなまとめ表を作りたいのです。
【自動】でというのは
シート1にデータを入力すると シート2にまとめ表が出来上がるということです。
説明が下手ですが よろしく御願いします。
大変申し訳ないのですが こちら オートフィルの使い方もわからないのです。
(蒔禁稽洌) 2016/03/21(月) 16:58
>>大変申し訳ないのですが こちら オートフィルの使い方もわからないのです。
オートフィル ではなく オートフィルター ですけど、これについては是非、習得しておかれたら便利ですよ。 ネットで検索すると、図解つきの説明ページがいくつもでてきます。 また、そのあと、是非、フィルターオプションも。これはオートフィルターより、さらに融通性にとんだ抽出ツールです。
それはともあれ、シート1に入力するだけでシート2ができあがるということですと、シート2に、ぎっしりと数式を埋め込むか あるいは、マクロで、たとえば シート2を開いた瞬間に自動で作成されるという方法が考えられます。
なんとなく、ご希望は数式処理なんですよね?
(β) 2016/03/21(月) 17:14
練習してみました。専門家さんから、早晩、スマートな数式が提示されると思いますが。 作業列も使います。
Sheet1 の F1 に =B1、 F2 に =IFERROR(VLOOKUP("*",IF(COUNTIF(F$1:F1,B$1:B$1000)=0,B$1:B$1000),1,FALSE),"") これを Ctrl/SHift/Enter で入力して、下にフィルコピー
Sheet2 の A1 に =IFERROR(IF(INDEX(Sheet1!$F:$F,QUOTIENT(COLUMN()-1,4)+1)="","",INDEX(Sheet1!$A$1:$Z$1000,SMALL(IF(Sheet1!$B$1:$B$1000=INDEX(Sheet1!$F:$F,QUOTIENT(COLUMN()-1,4)+1),ROW($B$1:$B$1000)),ROW(A1)),MOD(COLUMN()-1,4)+1)),"") これをCtrl/SHift/Enterで入力して、右にずっとフィルコピーし、そのまま下にずずずっとフィルコピー。
(β) 2016/03/21(月) 18:44
↑ Sheet2 の日付列は数値で表示されますので、表示書式で適切なものにしてください。 また、式の中の 1000 は、Sheet1のデータ行数をカバーできる数値にしてください。(1万行なら 10000)
(β) 2016/03/21(月) 18:48
(通りすがり) 2016/03/21(月) 19:04
通りすがりさんの示唆通り、たとえば数式でも、もっとスマートな(でも、難解な)ものも提示があるかもしれませんが 蒔禁稽洌さん(なんとお呼びするんでしょうか)と、そのお仲間が数式に詳しく、意味がちゃんと分かりメンテもできるということなら 大丈夫でしょうけど、そうではないなら、【自動化】はあきらめて、1行目をタイトル行にしてオートフィルターを使い お菓子で抽出してSheet2にコピペ、野菜で抽出してSheet2にコピペ、日用品で抽出して・・・・・ という操作が一番わかりやすくていいと思います。
コメントしたように、VBA処理もできます。たとえば、以下のコード、Sheet2のシートモジュールというところに貼り付けますと Sheet2を選択すると、その時点のSheet1の情報から最新の状態にまとめあげます。 でも、これも、マクロがわからないということになると、【迷惑をかけるエクセル】ということになりますねぇ。
Private Sub Worksheet_Activate() Dim c As Range Dim x As Long Dim i As Long Dim j As Long Dim v As Variant Dim cat As String Dim w As Variant Dim dic As Object
Application.ScreenUpdating = False
Set dic = CreateObject("Scripting.Dictionary") With Sheets("Sheet1").Range("A1").CurrentRegion '★元シート For Each c In .Columns("A").Cells cat = c.Offset(, 1).Value If Not dic.exists(cat) Then If IsArray(v) Then ReDim Preserve v(1 To .Rows.Count, 1 To UBound(v, 2) + 4) x = x + 4 Else x = 1 ReDim v(1 To .Rows.Count, 1 To 4) End If dic(cat) = Array(0, x) End If
w = dic(cat) w(0) = w(0) + 1 dic(cat) = w i = w(0) j = w(1)
v(i, j) = c.Value v(i, j + 1) = c.Offset(, 1).Value v(i, j + 2) = c.Offset(, 2).Value v(i, j + 3) = c.Offset(, 3).Value Next End With
UsedRange.ClearContents Range("A1").Resize(UBound(v, 1), UBound(v, 2)).Value = v
Set dic = Nothing
End Sub
(β) 2016/03/21(月) 19:53
フィルタリングを順次行ってコピペを繰り返す手順をおすすめしました。 オートフィルターではなく、フィルターオプションを使えば、直接抽出ができます。 この操作、もちろん手作業でもたいしたことはないのですが、これをマクロ化したものです。 先にアップしたコードを消した以下で置き換えてみてください。
なお、タイトル行はマクロの中で生成し、最後に消しています。
Private Sub Worksheet_Activate() Dim pos As Range
Application.ScreenUpdating = False
Me.UsedRange.ClearContents '転記前にクリア Set pos = Range("A1") '転記開始位置
With Sheets("Sheet1") 'タイトル行を作成 .Rows("1:1").Insert xlDown With .Range("A1").CurrentRegion.Columns("A:D") .Rows(1).Value = Array("日付", "大分類", "小分類", "数量") 'B列の一意の値リストを F列に作成 .Columns("B").AdvancedFilter Action:=xlFilterCopy, CopyToRange:=.Range("F1"), Unique:=True '根のため抽出条件先頭に = を付加して完全一致対応を行う With .Range("F2", .Range("F" & Rows.Count).End(xlUp)) .Value = Application.Text(.Value, "'=@") End With '抽出ループ処理 Do While .Range("F2").Value <> "" '抽出条件 .AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=.Range("F1:F2"), CopyToRange:=pos, Unique:=False .Range("F2").Delete '処理済み抽出条件を削除。次の条件がF2に繰り上がる Set pos = pos.Offset(, 4) '次の転記位置。4列右に移動。 Loop End With .Rows(1).Delete '元シートに挿入したタイトル行を削除 End With Rows(1).Delete 'できあがったシートのタイトル行を削除 End Sub
(β) 2016/03/21(月) 21:04
B列のすべての種類について、種類別に表を分けるのですか?
分けた表を 横に並べる必要があるんでしたっけ?
それは印刷のためとかですか?
シート2にコピーして、B列でソートして種類別に見分けられるようにする、
そういった簡単な方法もありますが、それではいけないですか?
別々に印刷したいなら、種類の区切りで改ページすることで対応できそうですけど。
ああ、βさんからいくつも対応案が提示されました。そちらを勉強なさってください。
(以下余談につき、質問者さんはスキップ下さい。)
# 迷惑をかけないExcelですか。
# 私も言及したこともあるんだけど、結構良いこと言っていますよね。
# ただ、現状批判としては首肯できる部分もあるが、改善策の提示は不十分かな。
# 私(田中さん)のセミナーを受講してみたいなことかも。
(γ) 2016/03/21(月) 21:12
アップした(β) 2016/03/21(月) 21:04 のコードですが、ステップ実行をすると、 .Range("F2").Delete '処理済み抽出条件を削除。次の条件がF2に繰り上がる ここで、ぐっと時間がかかります。100万行以上のセルの移動ですから、当然といえば当然ですが。 そこのところをセル削除ではない方法に変更しました。
Private Sub Worksheet_Activate() Dim pos As Range Dim c As Range
Application.ScreenUpdating = False
Me.UsedRange.ClearContents '転記前にクリア Set pos = Range("A1") '転記開始位置
With Sheets("Sheet1") 'タイトル行を作成 .Rows("1:1").Insert xlDown With .Range("A1").CurrentRegion.Columns("A:D") .Rows(1).Value = Array("日付", "大分類", "小分類", "数量") 'B列の一意の値リストを F列に作成 .Columns("B").AdvancedFilter Action:=xlFilterCopy, CopyToRange:=.Range("F1"), Unique:=True '抽出ループ処理 For Each c In .Range("F2", .Range("F" & Rows.Count).End(xlUp)) .Range("F2").Value = "'=" & c.Value '抽出条件 .AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=.Range("F1:F2"), CopyToRange:=pos, Unique:=False Set pos = pos.Offset(, 4) '次の転記位置。4列右に移動。 Next End With .Rows(1).Delete '元シートに挿入したタイトル行を削除 .Columns("F").ClearContents '抽出条件列クリア End With Rows(1).Delete 'できあがったシートのタイトル行を削除 End Sub
(β) 2016/03/21(月) 22:04
1)シート1で1行めに見出し挿入 2)シート2にピボットテーブル(表形式) 3)項目の数だけコピペで複製 4)各ピボットテーブルを項目でフィルター 5)見出しが邪魔であれば1行めを非表示
データを追加しても、自動更新されませんが、
「更新」をクリックするだけ。
項目が増えた時は、ピボットもコピペで追加。
(マナ) 2016/03/21(月) 22:29
読み返してみて、γさんと同じく、横に展開する必要性って?? と感じました。 縦に分けるなら、並び替えだけでいいわけですし、γさんがいわれるようにページ替えをすれば 印刷もわかれます。
D列が実際には数値で、その計算(合計とか平均とか)も今後の計画に入っているなら 並び替えたものを、小計機能で処理すれば、それなりのイメージのものができあがりますし。
(β) 2016/03/21(月) 23:05
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.