• 締切済み

csvのデータを複数条件で値を抽出したい

A列~E列のようなCSVのデータがあり、行に回答者氏名、列に質問番号(Q1~Q3)としてH列~K列のようにそれぞれの質問の回答が表示されるような表を作りたいと思っています。 回答者は500名くらいあるためコピペでは時間がかかりすぎるので関数で出来ないかと試してみているのですが上手くいきません。 どのような関数を使用すれば良いでしょうか?

みんなの回答

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

質問者は、どれぐらいの勉強し・経験者なのか書かないと、回答者が答えにくいのでは。 抜き出した後、そのデータをどう使う予定なのかも書かないと。 小生は回答を具体的に書く気はないが、視野を広げてもらう為に書いてみた。 表題(csvのデータを複数条件で値を抽出したい)だけからすると下記の方法がある。 しかしエクセルのシートを質問に掲示しているから、その旨を表題にもはっきり書くこと。 「エクセルのデータを条件をかけて抜き出す」という質問表現でよいのでは。 ・エクセルに読ませてエクセルで抽出する方法 エクセルを少しやれる程度なら、エクセルのシートにこのCSVファイルを読みこんで、、 そのエクセルのシートデータに対し条件を付けて抽出する方法 それには (1)操作のフィルタを使う方法 (2)関数だけでやる    (あ)作業列を使う方法    (い)作業列を使わない方法 この類の質問の回答には(2)の(あ)の回答がよく出るが、結構式が長く、その式の意味もわかりにくい。初心者なら(1)などの方法でどうか。 その中の(1)の(あ)の方法は、やややさしい。 (3)VBAを使う方法 考え方はすぐ思い付く簡単なこと。各行の特定の複数列の中身を、IF文で聞くことを全データ行で繰り返しするだけ。OR条件かAND条件か、がある。 フィルタの機能をVBAで使う手もある。 ・アクセスにこのCSVファイルをインポートして、アクセスの機能で抜き出す方法。 ・VBA、VBScriptの利用などになるが、直接CSV[ファイルをオ読んで  このデータ1レコードの中に、条件を満たすデータがあるかプログラムを組んで、街頭分を書き出すこともむつかしくはない。 上記はみなGoogleででも照会すれば具体的な方法は判る。 検索語 エクセル フィルタ 複数条件 エクセル 関数 抜出 複数条件 CSV VBA 抜出 もっとGoogleなどを検索して、読んで、やってみてそれから質問すべきです。

  • Prome_Lin
  • ベストアンサー率42% (201/470)
回答No.3

「VBScript」でプログラムを組みましたので、「Windows」限定です。 以下のプログラムをメモ帳かテキストエディタに貼り付けて、「~.vbs」という名前で保存します(「~」の部分は何でもかまいませんが、「.vbs」は必ず半角でなければなりません)。 できた「~.vbs」ファイル(のアイコン)に目的の「~.csv」ファイルを1つだけドラッグ&ドロップすると、結果のエクセルファイルが表示されます。 あとは、そのエクセルファイルを「F12」(「名前を付けて保存」)で、保存するなり、処理を続けるなりしてください。 なお、注意事項としては、まず、ドラッグ&ドロップするファイルは1つだけ。 次に、必ず「csv」ファイルでなければなりません。 最後に行数はいくらあっても構いませんが、構造が質問者のサンプルと全く同じでなければなりません。 すなわち、1行目が項目行で、2行目以降は、3行ごとにおひとりのデータが書き込まれている、ということです。 必ず、おひとり3行なければなりません。 Option Explicit Dim a, b, c, d, i, u, v, w, x, y, z Set u = WScript.Arguments If u.Count = 0 then End If If u.Count <> 1 Then MsgBox("ファイルは1つだけです") WScript.Quit 10 End If If LCase(Right(u(0), 3)) <> "csv" Then MsgBox("csvファイルだけです") WScript.Quit 10 End If Set v = CreateObject("Scripting.FileSystemObject") Set w = CreateObject("Excel.Application") w.Visible = True Set x = w.Workbooks.Add() Set y = x.Worksheets(1) Set z = v.OpenTextFile(u(0), 1) a = 1 b = Split(z.ReadLine, ",") y.Cells(a, 1).Value = "氏名" y.Cells(a, 2).Value = "Q1" y.Cells(a, 3).Value = "Q2" y.Cells(a, 4).Value = "Q3" Do Until z.AtEndOfStream b = Split(z.ReadLine, ",") c = Split(z.ReadLine, ",") d = Split(z.ReadLine, ",") a = a + 1 y.Cells(a, 1).Value = b(0) y.Cells(a, 2).Value = b(4) y.Cells(a, 3).Value = c(4) y.Cells(a, 4).Value = d(4) Loop z.Close Set z = Nothing Set y = Nothing Set x = Nothing Set w = Nothing Set v = Nothing 簡単なプログラムの説明です。 Set u = WScript.Arguments If u.Count = 0 then End If この部分は、ある意味、ドラッグ&ドロップされるのを待っています。 If u.Count <> 1 Then MsgBox("ファイルは1つだけです") WScript.Quit 10 End If ファイルが複数あれば終了。 If LCase(Right(u(0), 3)) <> "csv" Then MsgBox("csvファイルだけです") WScript.Quit 10 End If 「csv」ファイル以外なら終了。 Set v = CreateObject("Scripting.FileSystemObject") ファイルやフォルダを扱えるようにしています。 Set w = CreateObject("Excel.Application") エクセルを扱えるようにしています。 w.Visible = True エクセルを表示しています。 Set x = w.Workbooks.Add() Set y = x.Worksheets(1) エクセルのファイルを新規作成し、1番左端のシートを「y」にセット。 Set z = v.OpenTextFile(u(0), 1) ドラッグ&ドロップされた「csv」ファイルを開いています。 a = 1 b = Split(z.ReadLine, ",") 1行目は項目行として読み飛ばしています。 y.Cells(a, 1).Value = "氏名" y.Cells(a, 2).Value = "Q1" y.Cells(a, 3).Value = "Q2" y.Cells(a, 4).Value = "Q3" 項目名をエクセルに記入しています。 Do Until z.AtEndOfStream b = Split(z.ReadLine, ",") c = Split(z.ReadLine, ",") d = Split(z.ReadLine, ",") a = a + 1 y.Cells(a, 1).Value = b(0) y.Cells(a, 2).Value = b(4) y.Cells(a, 3).Value = c(4) y.Cells(a, 4).Value = d(4) Loop 「csv」ファイルを3行ずつ読み込んで処理しています。 z.Close 「csv」ファイルを閉じ、あとは、終了処理です。

  • ushi2015
  • ベストアンサー率51% (241/468)
回答No.2

こんにちは セルH2に、 =A2 セルH3に、 =IF(ROW(A1)>SUMPRODUCT(($A$2:$A$2000<>"")/COUNTIF($A$2:$A$2000,$A$2:$A$2000&""))-1,"",INDEX($A$2:$A$2000,MATCH(0,INDEX(0/ISERROR(MATCH($A$2:$A$2000,$H$2:H2,0)),),0))) で、セルH500位までフィルコピー セルI2に、 =IFERROR(INDEX($E:$E,MATCH(1,INDEX(($A:$A=$H2)*($D:$D=I$1),0),0)),"") で、セルI2をK2までフィルコピー セルI2:K2のフィルハンドルをダブルクリックし500行位までコピー CSVを開くExcelのバージョンは2007以降としています。

回答No.1

MATCH関数とINDEX関数を組み合わせて使うのがベターだと思われます。 関数の詳細は別途お調べください。 作業列を二つ使います。当方の図でいうとD列とE列。 まずD列には「氏名&質問」の列を作ります。 例えば、D2セルに   D2:=A2&B2 これを必要な範囲にコピー(フィル)しておきます。 E列の作業列は今回のご質問の本題とは外れますが、 元の表から「氏名が重複しないリスト」を表外に作るための作業列です。   E2:=IF(COUNTIF($A$2:A2,A2)=1,ROW(),"") として、これもまた必要な範囲にコピー(フィル)しておきます。 氏名が初めて出現する行に、行番号が入ります。 氏名が重複しないリストを作成します。 どうやら「氏名コード表」的なものがあるようですので、 ここはサラリと流しますので、読み飛ばしてくださってもOKです。   G2:=IF(COUNT(E:E)<ROW(A1),"",INDEX(A:A,SMALL(E:E,ROW(A1)))) として、下方少し多めにコピー・フィルしておきましょう。 作業列2(E列)が空白以外の行の氏名を抜き取ってリスト化されてきます。 さて、本題。 結論から言うと、   H2:INDEX($C$2:$C$10,MATCH($G2&H$1,$D$2:$D$10,0)) として、必要範囲にコピーしてやります。 MATCH関数で「作業列1(D列)から氏名&回答が合致する行」を取り、 INDEX関数で「行番号が合致する行のA列」を抜き取ってくる、 という仕組みです。 軽くややこしいのですが、覚えると便利な関数です。

関連するQ&A