こんにちは!
VBAになってしまいますが、一例です。
Sheet1のデータをSheet2に表示するようにしてみました。
Alt+F11キー → メニュー → 挿入 → 標準モジュール → VBE画面に
↓のコードをコピー&ペーストしてマクロを実行してみてください。
(Alt+F8キー → マクロ → マクロ実行です)
Sub Sample1() 'この行から
Dim i As Long, endRow As Long, wS1 As Worksheet, wS2 As Worksheet
Set wS1 = Worksheets("Sheet1") '←「Sheet1」は実際のSheet名に!
Set wS2 = Worksheets("Sheet2") '←「Sheet2」も実際のSheet名に!
Application.ScreenUpdating = False
wS2.Cells.ClearContents
endRow = wS1.Cells(Rows.Count, "A").End(xlUp).Row
wS1.Range("A1").Resize(, 2).Copy wS2.Range("A1")
wS1.Range("A:A").Insert
With Range(wS1.Cells(1, "A"), wS1.Cells(endRow, "A"))
.Formula = "=B1&C1"
.Value = .Value
.AdvancedFilter Action:=xlFilterInPlace, unique:=True
End With
endRow = wS1.Cells(Rows.Count, "A").End(xlUp).Row
Range(wS1.Cells(2, "B"), wS1.Cells(endRow, "C")).Copy wS2.Cells(2, "A")
With wS1
.ShowAllData
.Range("A:A").Delete
End With
For i = 2 To wS2.Cells(Rows.Count, "A").End(xlUp).Row
With wS1.Range("A1").CurrentRegion
.AutoFilter field:=1, Criteria1:=wS2.Cells(i, "A")
.AutoFilter field:=2, Criteria1:=wS2.Cells(i, "B")
endRow = .Cells(Rows.Count, "A").End(xlUp).Row
Range(.Cells(2, "C"), .Cells(endRow, "C")).Copy
wS2.Activate
ActiveSheet.Cells(i, "C").Select
Selection.PasteSpecial Paste:=xlPasteValues, Transpose:=True
End With
Next i
For i = 3 To wS2.UsedRange.Columns.Count
wS2.Cells(1, i) = wS1.Cells(1, "C") & i - 2
Next i
Application.ScreenUpdating = True
wS1.AutoFilterMode = False
End Sub 'この行まで
こんなんではどうでしょうか?m(_ _)m
別の質問に触発されて、自ブックに対するADOでの抽出をやってみました。xl2003以前については、自ブックに対して適用するとメモリリークが発生するというバグが放置されていて使えません。勤務先もそろそろxl2007以降のフォーマットが標準になりそうなので、復習してみました。
フィールド名決め打ちならもっとシンプルなコードになりますが、極力汎用化しようとトライしてみました。
後出しなので、「種別」にも対応しています。
なお、この方法ならアレンジすればCSVから直にできるかもしれませんが、上記の理由でSheet1に読み込んでからの処理です。
Const adOpenFowardOnly As Long = 0
Sub test()
Dim cn As Object
Dim rs0 As Object, rs As Object, rs2 As Object
Dim mySQL As String, mySQL2 As String
Dim destRange As Range
Dim i As Long, j As Long
Set cn = CreateObject("ADODB.Connection")
With cn
.Provider = "Microsoft.ace.OLEDB.12.0"
.connectionstring = "Data Source=" & ThisWorkbook.FullName & ";" & _
"Extended Properties='Excel 12.0; HDR=YES'"
.Open
End With
'rs0 フィールド名取得用
Set rs0 = CreateObject("ADODB.Recordset")
rs0.Open "SELECT * FROM [Sheet1$];", cn, adOpenFowardOnly
'rs グループ化したRecordset
Set rs = CreateObject("ADODB.Recordset")
mySQL = "SELECT F1,F2,F3 FROM [Sheet1$] GROUP BY F1,F2,F3;"
For i = 1 To 3
mySQL = Replace(mySQL, "F" & CStr(i), rs0.Fields(i - 1).Name)
Next i
rs.Open mySQL, cn, adOpenFowardOnly
Sheets("Sheet2").Cells.Clear
Set destRange = Sheets("Sheet2").Range("A2")
For i = 1 To 3
destRange.Offset(, i - 1).Item(0) = rs0.Fields(i - 1).Name
Next i
For i = 1 To 100
destRange.Offset(, 2 + i).Item(0) = rs0.Fields(3).Name & CStr(i)
Next i
Do Until rs.EOF
For i = 0 To 2
destRange.Offset(, i).Value = rs.Fields(i).Value
Next i
mySQL2 = "SELECT F4 FROM [Sheet1$] WHERE F1='F1Value' AND F2 = 'F2Value' AND F3 = 'F3Value';"
For i = 1 To 4
If i < 4 Then mySQL2 = Replace(mySQL2, "F" & CStr(i) & "Value", rs.Fields(i - 1).Value)
mySQL2 = Replace(mySQL2, "F" & CStr(i), rs0.Fields(i - 1).Name)
Next i
'rs2 グループ化した組み合わせ毎に該当するリストを取得
Set rs2 = CreateObject("ADODB.Recordset")
rs2.Open mySQL2, cn, adOpenFowardOnly
j = 3
Do Until rs2.EOF
destRange.Offset(, j).Value = rs2.Fields(0).Value
rs2.MoveNext
j = j + 1
Loop
Set rs2 = Nothing
rs.MoveNext
Set destRange = destRange.Offset(1, 0)
Loop
Set rs0 = Nothing
Set rs = Nothing
cn.Close: Set cn = Nothing
End Sub
No。5です。
>本当は
>県名,品物名,種別,購入者1,購入者2・・・
というコトはSheet1が↓の画像のような配置になっているという前提です。
前回は時間がなかったので慌ててコードを作ってしまいました。
前回とはちょっと違いますが、↓のコードでマクロを試してみてください。
Sub Sample2()
Dim i As Long, j As Long, endRow As Long, lastRow As Long, endCol As Long
Dim wS1 As Worksheet, wS2 As Worksheet
Set wS1 = Worksheets("Sheet1")
Set wS2 = Worksheets("Sheet2")
Application.ScreenUpdating = False
wS2.Cells.ClearContents
With wS1
.Range("A1").Resize(, 3).Copy wS2.Range("A1")
endRow = .Cells(Rows.Count, "A").End(xlUp).Row
.Range("A:A").Insert
With .Range("A1").Resize(endRow)
.Formula = "=B1&C1"
.Value = .Value
End With
.Range(Cells(1, "A"), Cells(endRow, "A")).AdvancedFilter Action:=xlFilterInPlace, unique:=True
lastRow = .Cells(Rows.Count, "A").End(xlUp).Row
.Range(Cells(2, "B"), Cells(lastRow, "D")).Copy wS2.Cells(2, "A")
.ShowAllData
.Range("A:A").Delete
For i = 2 To wS2.Cells(Rows.Count, "A").End(xlUp).Row
.Range("A1").AutoFilter field:=1, Criteria1:=wS2.Cells(i, "A")
.Range("A1").AutoFilter field:=2, Criteria1:=wS2.Cells(i, "B")
lastRow = .Cells(Rows.Count, "A").End(xlUp).Row
Range(.Cells(2, "D"), .Cells(lastRow, "D")).Copy
wS2.Activate
ActiveSheet.Cells(i, "D").Select
Selection.PasteSpecial Paste:=xlPasteValues, Transpose:=True
Next i
endCol = wS2.UsedRange.Columns.Count
For j = 4 To endCol
wS2.Cells(1, j) = .Range("D1") & j - 3
Next j
End With
wS1.AutoFilterMode = False
Application.ScreenUpdating = True
End Sub
今度はどうでしょうか?m(_ _)m
お礼
ありがとうございます。 このソースのまま実現できてしまいました。 でもこんな見も知らず人の質問に、こうもパッとソースを書けてしまうスキルに感服です。 回答者さんにとってはそんな簡単な事なんでしょうか? 実は後から、C列に「種別」という項目が追加されてしまい(値は、野菜、果物等)、 購入者の列がD列に移動してしまいました。 ソースを手直ししてD列が横並びになるようにカスタマイズできましたが、 項目名と値が、 県名,品物名,購入者1,購入者2・・・ 青森,りんご,果物,西田さん,斉藤さん のように1列ずれてしまいました。 本当は 県名,品物名,種別,購入者1,購入者2・・・ 青森,りんご,果物,西田さん,斉藤さん としたいのですが・・・ それを解析するのが今後の課題です。 (教えてもらえると嬉しいです。)