データの統合方法と結果

このQ&Aのポイント
  • 上下の値が一致したら、他の列の上下を統合し1行にする方法を解説します。
  • 16000件のデータを、5000件に統合しました。同じ名前の人物の報告は1つのフィールドにまとめられています。
  • マクロや関数を使用して、効率的にデータの統合が行えます。
回答を見る
  • ベストアンサー

上下の値が一致したら、他の列の上下を統合し1行に

下記のようなデータがあります。 「名前」「内容」「日時」 田中  報告1  日時 田中  報告2  日時 田中  報告3  日時 吉田  報告1  日時 吉田  報告2  日時 佐々木 報告1  日時 藤森  報告1  日時 藤森  報告2  日時 豊富  報告1  日時 豊富  報告2  日時 16000件あり、同一名で重複行を消すと5000件になります。 このデータを下記の通り、同じ人物の報告は1行のデータに変換したいです。 ↓名前が同一だったら内容と日時を全て繋げて1つのフィールドに入れる 「名前」「内容」 田中  [日時:報告1、日時:報告2、日時:報告3] 吉田  [日時:報告1、日時:報告2] 佐々木 [日時:報告1] 藤森  [日時:報告1、日時:報告2] 豊富  [日時:報告1、日時:報告2] 関数を駆使して出来るのでしょうか。 マクロでしょうか。 お知恵をお貸しください。 尚、解りやすいように報告1、報告2と数字を付けていますが、 実際のデータには数字は付いていません。 何卒、宜しくお願い致します。

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

  • ベストアンサー
  • cj_mover
  • ベストアンサー率76% (292/381)
回答No.5

こんにちは。 オーダーに忠実に書きました。 > 名前が同一だったら内容と日時を全て繋げて1つのフィールドに入れる これはVBAでやるしかないですね。 「どこ?」のデータを「どこ?」に出すか、 条件を開示されていない部分は、 そちらで運用に合わせて書き換えてください。 こちらで仮想の設定として、 アクティブなシートの セルA1を含む一連の領域  を 新しいシートの セルA1を先頭とした領域  に出力 するように書いてあります。 何かうまく出来ないことでもあれば、 補足欄にでも書いてみて下さい。 Sub Re8757443() Dim arrK(), arrI() Dim oDict As Object Dim c As Range Dim i As Long   Set oDict = CreateObject("Scripting.Dictionary")   For Each c In Range("A1").CurrentRegion.Resize(, 1)  ' ← 元データはどこら辺 ? "A1" ?     If oDict.Exists(c.Value) Then       oDict(c.Value) = oDict(c.Value) & "、" & c(1, 3).Value & " " & c(1, 2).Value     Else       oDict(c.Value) = c(1, 3).Value & " " & c(1, 2).Value     End If   Next   arrK() = oDict.Keys   arrI() = oDict.Items   Worksheets.Add After:=ActiveSheet ' ← 出力先は ? 新規のシート ?   For i = 1 To oDict.Count     Cells(i, "A") = arrK(i - 1) ' ← 出力先は ? "A"列に ?     Cells(i, "B") = arrI(i - 1) ' ← 出力先は ? "B"列に ?   Next i   Set oDict = Nothing   Range("A1").CurrentRegion.Columns.AutoFit ' ← 出力先はどこら辺 ? "A1" ? End Sub

kzkz-16
質問者

お礼

とっても参考になるスクリプトありがとうございます! インデントされていて見やすく、こちらで変更が必要な部分も明確になっていて、 尚且つ、実行結果の画像が「1つのフィールドに繋げて入れる」という希望通りの動作である事が一目で解かる回答であった為、とても良い回答だと思いました! 実際は繋げる内容は最大で53列&40行にも及ぶのですが、 頂いたサンプルをカスタマイズして、無事に希望通りのスクリプトを作る事ができました!

その他の回答 (6)

  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.8

#7です。 すみません、 Do Until rs.EOF mySQL = "select 日時,内容 from [" & srcSheet.Name & "$] where 名前='" & rs.Fields(0).Value & "';" <以下略> に変更をお願いします。 ご質問では集計時日時が先でした。

  • mitarashi
  • ベストアンサー率59% (574/965)
回答No.7

きっと受けないと思いますが、最近覚えた技で参戦してみます。 Sheet1のデータをSheet2に書き出します。xl2007以降対応のコードです。xl2003以前では小手直しの必要があります。 Sub test() Dim cn As Object, rs As Object, rs2 As Object Dim mySQL As String, buf As String Dim srcSheet As Worksheet, destSheet As Worksheet Dim mycell As Range Const adClipString As Long = 2 Set cn = CreateObject("ADODB.Connection") Set rs = CreateObject("ADODB.Recordset") Set rs2 = CreateObject("ADODB.Recordset") With cn .Provider = "Microsoft.ace.OLEDB.12.0" .ConnectionString = "Data Source=" & ThisWorkbook.FullName & ";" & _ "Extended Properties='Excel 12.0; HDR=Yes'" .Open End With Set srcSheet = ThisWorkbook.Sheets("Sheet1") Set destSheet = ThisWorkbook.Sheets("Sheet2") destSheet.Range("A1:B1").Value = Array("名前", "内容") Set mycell = destSheet.Range("A2") mySQL = "select distinct 名前 from [" & srcSheet.Name & "$];" rs.Open mySQL, cn Do Until rs.EOF mySQL = "select 内容,日時 from [" & srcSheet.Name & "$] where 名前='" & rs.Fields(0).Value & "';" rs2.Open mySQL, cn buf = rs2.GetString(adClipString, 5, ":", ",") buf = Left(buf, Len(buf) - 1) mycell.Value = rs.Fields(0).Value mycell.Offset(0, 1).Value = buf Set mycell = mycell.Offset(1, 0) rs2.Close rs.movenext Loop Set rs2 = Nothing rs.Close Set rs = Nothing cn.Close Set cn = Nothing End Sub

kzkz-16
質問者

お礼

スクリプトを考えて頂きありがとうございました。 実行結果のサンプル画像が希望通りを示したものになっていましたが 生憎、2003であった為、別の回答のスクリプトを優先に試しました。 すみません。 でも、参考になりました!

  • cj_mover
  • ベストアンサー率76% (292/381)
回答No.6

#5、cjです。#5に修正、自己レスです。 c(1, 3).Value 2か所ある記述を、どちらも c(1, 3).Text に書き換えてみて下さい これで、元の表に「表示された日付」をトレースできます。 #5のままでは、元の表の「表示値」をトレースしてしまうので、 臨んだ結果にならない場合があるかも知れませんので。 以上。修正案でした。

  • bunjii
  • ベストアンサー率43% (3589/8248)
回答No.4

>名前が同一だったら内容と日時を全て繋げて1つのフィールドに入れる 関数では内容と日時を1組ずつ1つのフィールドへ抽出することになるでしょう。 貼付画像は提示された模擬データのみを使ってExcel 2013で検証したものです。 日時は判別できるように末尾に数字を加えました。 「名前」を単一化する数式をE2へセットしました。 「内容」は「内容1」、「内容2」、「内容3」のようにF列からI列へフィールドを作成しました。 E2=IFERROR(INDEX(A$1:A$1000,SMALL(IFERROR(MATCH(A$1:A$1000,A$1:A$1000,0),""),SUM(COUNTIF(A$1:A$1000,E$1:E1),1))),"") この数式は配列数式になりますのでCtrlとShiftを押しながらEnterキーで確定してください。 F2=IFERROR(INDEX($C:$C,SUMPRODUCT(LARGE(($A$2:$A$11=$E2)*ROW(F$2:F$11),COUNTIF($A$2:$A$11,$E2)-COLUMN(A1)+1)),1),"")&":"&IFERROR(INDEX($B:$B,SUMPRODUCT(LARGE(($A$2:$A$11=$E2)*ROW(F$2:F$11),COUNTIF($A$2:$A$11,$E2)-COLUMN(A1)+1)),1),"") こちらは通常通りEnterキーのみで確定して問題ありません。 日時については実際のデータに合わせてシリアル値をTEXT関数で文字列に置換してから連結する必要があるでしょう。 F2セルをオートフィルで右へI2セルへコピーしました。 E2からI2セルを選択して下へ必要数コピーすれば良いでしょう。 実際の処理ではデータ数が多いので自動再計算にすると待ち時間が長くなるでしょう。 ストレス解消には手動再計算にして必要時のみF9キーで再計算させることをお勧めします。

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

こんにちは! VBAでの一例です。 元データはSheet1に↓の画像のような配置であるとして、Sheet2に表示するとします。 尚、Sheet3を作業用のSheetとして使用しますので、Sheet3は使っていない状態にしておいてください。 Alt+F11キー → メニュー → 挿入 → 標準モジュール → VBE画面のカーソルが点滅しているところに ↓のコードをコピー&ペースト → Excel画面に戻りマクロを実行してみてください。 (Alt+F8キー → マクロ → マクロ実行です) Sub Sample1() 'この行から Dim i As Long, j As Long, lastRow As Long, wS2 As Worksheet, wS3 As Worksheet Set wS2 = Worksheets("Sheet2") Set wS3 = Worksheets("Sheet3") Application.ScreenUpdating = False wS2.Cells.Clear With Worksheets("Sheet1") lastRow = .Cells(Rows.Count, "A").End(xlUp).Row .Range("A:A").AdvancedFilter Action:=xlFilterCopy, copytorange:=wS2.Range("A1"), unique:=True For i = 2 To wS2.Cells(Rows.Count, "A").End(xlUp).Row .Range("A1").AutoFilter field:=1, Criteria1:=wS2.Cells(i, "A") Range(.Cells(2, "B"), .Cells(lastRow, "C")).SpecialCells(xlCellTypeVisible).Copy wS3.Range("A1").PasteSpecial Paste:=xlPasteAll, Transpose:=True For j = 1 To wS3.Cells(1, Columns.Count).End(xlToLeft).Column wS2.Cells(i, Columns.Count).End(xlToLeft).Offset(, 1) = wS3.Cells(2, j) & " " & wS3.Cells(1, j) Next j wS3.Cells.Clear Next i wS2.Range("A1").CurrentRegion.Borders.LineStyle = xlContinuous wS2.Columns.AutoFit .AutoFilterMode = False End With Application.ScreenUpdating = True wS2.Activate MsgBox "処理完了" End Sub 'この行まで ※ 関数でないのでSheet1に変更があるたびに マクロを実行する必要があります。m(_ _)m

回答No.2

16000件で報告1、報告2、報告3を試した結果です。

関連するQ&A

  • CSVの列上下で照合し、一致したら繋げて1行にする

    下記のようなCSVデータがあります。 「名前」「内容」「日時」 田中  報告1  日時 田中  報告2  日時 田中  報告3  日時 吉田  報告1  日時 吉田  報告2  日時 佐々木 報告1  日時 藤森  報告1  日時 藤森  報告2  日時 豊富  報告1  日時 豊富  報告2  日時 16000件あり、同一名で重複行を消すと5000件になります。 このデータを下記の通り、同じ人物の情報は1行のデータに変換したいです。 ↓上下で名前フィールドが一致したら、他の列の内容と日時を全て繋げて1つのフィールドに入れる 「名前」「内容」 田中  [日時:報告1、日時:報告2、日時:報告3] 吉田  [日時:報告1、日時:報告2] 佐々木 [日時:報告1] 藤森  [日時:報告1、日時:報告2] 豊富  [日時:報告1、日時:報告2] 1行ずつ処理してゆくスクリプトはサンプルが多くあり、作る事ができました。 <?php $openfile = file_get_contents('list.csv'); //csvをutf8に $openfile = mb_convert_encoding($openfile,"utf-8","auto"); //1行ずつ分ける $csv_gyo = explode("\n", $openfile); //1行ずつ読み込みながらのループ処理 foreach($csv_gyo as $kurikaeshi) { //カンマごとに分ける $ret_csv = explode(",", $kurikaeshi); echo("".$ret_csv[0]."<br />"); } 何卒、宜しくお願い致します。

    • ベストアンサー
    • PHP
  • Excel 重複値を検索し全て表示させる関数

    Sheet1の1行目には見出しがあり、A列とB列の2行目から下にデータが入っています。(約200行) A列     B列 田中    13 山本     8 谷口    11 鈴木    6 田中    10 佐々木    9 奥村     15 佐々木   15 佐々木   20 ・ ・ ・ Sheet2のA列1行目から下には別のデータが入っています。(約600行) A列 太田川 山村 田中 多賀先 鈴木 奥村 幸田 ・ ・ ・ Sheet2のA列のデータと完全一致するデータ(名前)をSheet1のA列から探して、同じ名前があれば、その隣のB列にある数値をSheet2のB列に貼り付ける(B列が重複の場合、下に張り付ける。但し、A列の名前は1行目は表示、2行目からは表示、空欄でも構いません)。 見つからない場合はSheet2のB列は空欄のままです。 Sheet2 A列      B列 太田川      山村 田中    13        10 多賀先 鈴木     6 奥村    15 佐々木   9       15       20 幸田 ・ ・ ・ 何卒、ご指導の程宜しくお願い致します。

  • 同じ値を同じ行×列で見つけた場合のセルの塗潰しは?

    どなたかご存知でしたらご回答よろしくお願いします。 ●質問 下記の様に、前回数字、今回数字として10行×5列の中にそれぞれ 1~31迄の数字が重複ありで入っています。 【前回数字】の1 4 5 9 12の1はセルのA1、 1 8  15 25 26の26はE10とします。 【今回数字】の4 5 9 12 16の4はセルのG1、 5 13 14 23 28の28はK10とします。 A1=G1、B2=H2・・・D10=G10、E10=K10とそれぞれの値が同じかチェックを 行い、等しい場合(例:29(E3=K3)、18(B4=H4)、21(C4=I4)、22(D4=J4)・・・)には、【今回数字】側のセル(K3、H4、I4、J4・・・)を 塗潰し、塗潰したセルを起点として8方向(上、右、左、下、右上、左上、左下、右下)のセル塗潰す方法が知りたいです。   【前回数字】    【今回数字】  1  4 5 9 12   4  5  9  12  16  2  3 6 8 27   3  25 26  27  28  10 14 15 28 29  8  10 11  14  29  16 18 21 22 26  15  18 21  22  23  7 11 13 24 25   1  2  6  7  13  2  5 7 10 16   1  8  9  15  25  3 11 12 18 28   2  10  12  18  26  6  9 13 21 29   3  6  11  16  21  4 14 22 24 27   4  7  22  27  29  1  8 15 25 26   5  13 14  23  28  ●注意事項  ・使用するエクセルは2010です。  ・【前回数字】、【今回数字】共に、セルの中の数字は    1~31迄の数字がランダムに入ります。 以上、よろしくお願いします。

  • 【Excel】同じ行で2つの各値が一致する行の参照

    エクセルで【Sheet1】のデータから 【Sheet2】【Sheet3】の表を作成したいのですが、 いろいろ試してもわかりません。 どうか教えてください。 【Sheet1】 A B C   D E 1 2001 佐賀県 1 山田 090-000-0000 2 2001 愛媛県 2 佐藤 090-111-1111 3 2001 静岡県 4 伊藤 090-222-2222 4 2001 岡山県 5 中野 090-333-3333 5 2002 三重県 1 近藤 090-444-4444 6 2002 福島県 2 田中 090-555-5555 7 2002 岐阜県 3 吉田 090-666-6666 以下600行ほど続きます。 【Sheet2】 A B C 1 2001←入力します 2 1 山田 090-000-0000 3 2 佐藤 090-111-1111 4 4 伊藤 090-222-2222 5 5 中野 090-333-3333 【Sheet3】 A B C 1 2002←入力します 2 1 近藤 090-444-4444 3 2 田中 090-555-5555 4 3 吉田 090-666-6666 【Sheet2】【Sheet3】のA1には、 【Sheet1】のA1の値を入力します。 A2,B2,C2 A3,B3,C3 ... それぞれのセルにどんな数式を入れたら 表ができあがりますででしょうか? 【Sheet2】【Sheet3】共に、VLOOKUPで =VLOOKUP(A1,Sheet1!A1:D7,3,) =VLOOKUP(A1,Sheet1!A1:D7,4,)を使うと、 2行目はうまくいきますが、 3行目から狂ってきます。 頭が沸騰してきました! わかる方に教えていただいたほうが早いですネ、 どうぞご享受よろしくお願いいたします。

  • セルの値が同じ行を条件に従って行削除するマクロ

    A~E列までデータがあり 行数は約30,000行あります。 A列は半角英数字と-で桁数は11桁又は14桁です。 数字のみもあれば数字と英字の組み合わせもあります。 (英字はどこの桁にあるか何個あるかは不規則です) 例 ABCD123456789X 124345678901234 55555-55555 ABC12345DEF678 E列には半角の 1 か 2 しかありません。 A列が同じ値の行を検出して重複している行は1行だけ残して 後は行削除をしたいです。 行削除はE列の値によって判定したいです。 重複行は1つの値に対して何行あるか不明です。 30,000行のうち、重複行を削除すると10,000行くらいになる予定です。 (1)重複行にてE列の値が1だけの場合    どれでもいいので1行残して残りは行削除 (2)重複行にてE列の値が2だけの場合   どれでもいいので1行残して残りは行削除 (3)重複行にてE列の値が1も2もある場合   E列の値が2の行をどれでもいいので1行残して残りは削除 例 (1) 1234567890XXXX-1 1234567890XXXX-1 1234567890XXXX-1 ↓ 1234567890XXXX-1 (2) 123ABCDE901234-2 123ABCDE901234-2 ↓ 123ABCDE901234-2 (3) 12345678901234-1 12345678901234-2 ↓ 12345678901234-2 ABC45678901234-1 ABC45678901234-2 ABC45678901234-1 ABC45678901234-2 ↓ ABC45678901234-2 手作業では5時間かかりましたがミスだらけです。 まだ数ファイル残っており手作業では厳しいのでマクロを 作成したいのですが、どう記述していのかまったく検討が付きません。 どうかよろしくお願いします。

  • Excel VBAで値が重複する行を削除する

    Excel2000を使っています。 シートAに数千件のデータがあります。 シートBのE列にある文字とシートAのD列の文字が重複する場合に、シートAの重複するセルがある行を削除する(且つできれば行のデータを抜き出すVBAを作ろうと考えています。 最近VBAの初心者本をやっと理解したところで、ちんぷんかんぷんとまではいかないけど、知恵熱がでました。 仕事なので自分でなんとかすべきかと思いますが、きっかけの調べ方がまずわからない。 どなたか、解かるきっかけだけでも与えて頂けないでしょうか。とくに、別シートの値と重複する値を探す場合に何をいれるかわかればきっと道は開けると思うんですが…。 初めての質問なので、質問内容が至らなかったらもうしわけありません。

  • Flexgridで選択行の列の値を取得したい

    いつも参考にさせていただいております。 現在データベースからデータを取ってきてFlexgridに表示するプログラムを作りました。 そのフォームでFlexgridのある行を選択して削除ボタンを押すと、Flexgridの選択した行とデータベースのIDと一致した行を削除するようにしたいと思っています。 しかし、データベースの削除を行うためにFlexgridの選択した行のID列の値を取得しなければならないと思うのですが、どうやって取得すればよいのか分かりません。 どのようにすればよいでしょうか? サンプルなどあればよろしくお願いいたします。 ID  名前  部 ------------------ 01  佐藤  野球 02  鈴木  サッカー  ←例えばこの行を選択したら02を抜き出したい 03  田中  剣道 04  山田  柔道 05  高橋  バレー 環境:Window XP Pro、FlexGrid for .NET 4.0J、SQL Server 2005

  • 列に並んだ数字群から一致する数字の行番号を抽出

    下記のように B列に数字が縦に並んでいます。 28.11684736 28.12102177 28.12519803 28.12937616 28.13355614 28.13773798 28.14192168 28.14610723 28.15029464 28.15448391 28.15867503 28.16286801 28.16706285 28.17125955 28.1754581 この数字群から、例えば 28.15448391 に一致する数字の行を見つけて その行番号を抽出するコードはどのように記述したらよいのでしょうか。 番号はA1のセルに置きます。 但し、条件があって Excel2000~Excel2003の全てのバージョンに共通する こと。そして列のデータ数が約10000程度はあることです。どこから 手をつけてよいのか判らないので、よろしくお願いします。 簡単な例では下記でもよさそうですが。より早く求めるには???  A= Range("B65536").End(xlUp).Row I=0 Do I=I+1 Loop until Cells(I,2).value=28.15448391  Range("A1")=I

  • エクセルSheet1,2を使っての行ごとでの値の返し方

    Sheet1にデータを行ごとに入れていきます。 Sheet2にSheet1のデータを行ごとに返します。 例えば下記のようなデータがSheet1にあります。 行/列  A     B     C    D     登録番号 申込み日  氏名   住所  1  h1234  15年2月  山田太郎 東京都品川区   2  k0022  14年8月  田中次郎 千葉県浦安市   3  m3651  15年1月  鈴木三郎 埼玉県川口市   4  g7890  13年6月  佐藤四郎 神奈川県横浜市 Sheet2のA1にSheet1の行3のデータを返すため3と入れます。登録番号を入れたいので、次のような関数を入れてみましたがうまく出来ませんでした。 =IF(ISNUMBER(A1),INDIRECT(Sheet1!A3&A1),"") 何がいけないのかわかりませんでした。 それに、出来れば登録番号の数字(全て4桁です)返したいのですが、さらに、MIDを使えばよいのですか?説明が十分かどうかわかりませんがアドバイス宜しくお願い致します!

  • ROW()関数の使い方について

    今、フィルタオプションを使わずに、 重複したデータが空白になるように関数を作っています。 B行に業務内容を書き込み(ミーティング、書類作成 など) C行に重複した業務内容を空白で表示させるという関数を 完成させたいのですが、ROW()関数を使い下にフィルしたとき、 『B$2:B3』の3という数字部分が1つずつ変わるようにしたいのですが、 下記式のような使い方ではエラーになります。 どのようにすればよいのでしょうか?    A         B           C         D 1 氏名    業務内容      業務内容 2 田中    ミーティング    ミーティング 3 田中    書類作成      書類作成 4 田中    ミーティング    (空白) 5  C4=IF(MATCH(B4,"B$2:B"&ROW()-1,0),"",B4)

専門家に質問してみよう