一つ目:
テキストとして一行つづ読んで、区切りコンマまたはタブでsplitして処理する、この方法はメリットは高速で簡単、デメリットはフィルド内改行やダブルクォーテーションがあったら、おかしくなること
二つ目:
Workbookでcsvを開き、range単位で処理する方法。方法1と比べてちょっと遅いですが、Excelで正常に開けるCSVなら、問題なく処理できるというのはポイント。※注意:連想配列Scripting.Dictionaryを使うには、「ツール」⇒「参考設定」の中に「Microsoft Scripting Runtime」をチェック入れてね
それでは2番目の方法を紹介します:
例えばこんなCSVがあります
名前 | 学校名 | 学年 | クラス | 国語 | 英語 | 数学 |
---|---|---|---|---|---|---|
田中 | 一小 | 3年 | 1組 | 90 | 80 | 70 |
佐藤 | ニ小 | 3年 | 1組 | 34 | 60 | 90 |
渡辺 | 一小 | 2年 | 2組 | 78 | 76 | 80 |
田中 | ニ小 | 1年 | 3組 | 66 | 66 | 78 |
中田 | 一小 | 2年 | 1組 | 67 | 89 | 53 |
山田 | ニ小 | 3年 | 2組 | 43 | 57 | 78 |
まずは一個モジュールを作りましょう。例えば名前はcsv_reader。内容は下記:
Option Explicit Public gReits As New Scripting.Dictionary '格納先の連想配列 Sub CSV_Read2() Dim FileType, Prompt As String Dim FileNamePath As Variant Dim dicHeader As New Scripting.Dictionary Dim dicHeaderRev As New Scripting.Dictionary Dim wb As New Workbook Dim st As New Worksheet Dim csvrow As Range Dim csvfield As Range Dim strFolder As String Dim FSO As Object 'まずはcsvファイルを選択するダイアログボックス FileType = "CSV ファイル (*.csv),*.csv" Prompt = "CSV File を選択してください" '操作したいファイルのパスを取得します FileNamePath = SelectFileNamePath(FileType, Prompt) 'キャンセルボタンが押された If FileNamePath = False Then End End If '格納先の連想配列を空にする gReits.RemoveAll 'csvファイルを開く Set wb = Workbooks.Open(FileNamePath) 'シートをセット(csvファイルはsheet1しかない) Set st = wb.Sheets(1) '内容の有るすべてのレンジから一行つづ読み込む For Each csvrow In st.UsedRange.Rows '一行目はタイトル、タイトル変数に格納 If csvrow.row = 1 Then 'タイトル行のすべての列 For Each csvfield In csvrow.Columns 'タイトル名と列の情報をkey,item交代でそれそれ格納し dicHeader.Add csvfield.Value, csvfield.Column dicHeaderRev.Add csvfield.Column, csvfield.Value Next Else '2行目以降の処理 '今後使うときにやりやすいようにデータは階層構造として格納する '第一階層キーはcsvの学校の値 '第二階層キーは学年 '第三階層キーはクラス '第四階層キーはなく、csvの生徒のデータを格納する場所 'もし第一階層キーまだ登録してなければ登録します If Not gReits.Exists(Cells(csvrow.row, dicHeader.Item("学校名")).Value) Then gReits.Add Cells(csvrow.row, dicHeader.Item("学校名")).Value, New Scripting.Dictionary End If 'もし第ニ階層キーまだ登録してなければ登録します If Not gReits.Item(Cells(csvrow.row, dicHeader.Item("学校名")).Value).Exists(Cells(csvrow.row, dicHeader.Item("学年")).Value) Then gReits.Item(Cells(csvrow.row, dicHeader.Item("学校名")).Value).Add Cells(csvrow.row, dicHeader.Item("学年")).Value, New Scripting.Dictionary End If 'もし第三階層キーまだ登録してなければ登録します If Not gReits.Item(Cells(csvrow.row, dicHeader.Item("学校名")).Value).Item(Cells(csvrow.row, dicHeader.Item("学年")).Value).Exists(Cells(csvrow.row, dicHeader.Item("クラス")).Value) Then gReits.Item(Cells(csvrow.row, dicHeader.Item("学校名")).Value).Item(Cells(csvrow.row, dicHeader.Item("学年")).Value).Add Cells(csvrow.row, dicHeader.Item("クラス")).Value, New Scripting.Dictionary End If '最後列ごとで、タイトルと値を連想配列に格納する For Each csvfield In csvrow.Columns gReits.Item(Cells(csvrow.row, dicHeader.Item("学校名")).Value).Item(Cells(csvrow.row, dicHeader.Item("学年")).Value).Item(Cells(csvrow.row, dicHeader.Item("クラス")).Value).Add dicHeaderRev.Item(csvfield.Column), csvfield.Value Next End If Next wb.Close SaveChanges:=False set wb = nothing set st = nothing 'ここまで、csvのデータがすべてグローバル連想配列変数gReitsに格納したはず、あとは好きなように使うだけ call printOut End Sub Function SelectFileNamePath(FileType, Prompt) As Variant SelectFileNamePath = Application.GetOpenFilename(FileType, , Prompt) End Function Sub printOut() Dim gakkou As Variant Dim gakunen As Variant Dim class As Variant If gReits.Count > 0 Then For Each gakkou In gReits.Keys Debug.Print "学校名:" & gakkou For Each gakunen In gReits.Item(gakkou).Keys Debug.Print vbTab & "学年:" & gakunen For Each class In gReits.Item(gakkou).Item(gakunen).Keys Debug.Print vbTab & vbTab & class Debug.Print vbTab & vbTab & vbTab & gReits.Item(gakkou).Item(gakunen).Item(class).Item("名前") & "⇒" & _ "国語:" & gReits.Item(gakkou).Item(gakunen).Item(class).Item("国語") & _ "英語:" & gReits.Item(gakkou).Item(gakunen).Item(class).Item("英語") & _ "数学:" & gReits.Item(gakkou).Item(gakunen).Item(class).Item("数学") Next Next Next End If End Subイミディエイトウィンドウの出力はこんな感じ
学校名:一小
学年:3年
1組
田中⇒国語:90英語:80数学:70
学年:2年
2組
渡辺⇒国語:78英語:76数学:80
1組
中田⇒国語:67英語:89数学:53
学校名:ニ小
学年:3年
1組
佐藤⇒国語:34英語:60数学:90
2組
山田⇒国語:43英語:57数学:78
学年:1年
3組
田中⇒国語:66英語:66数学:78
0 件のコメント:
コメントを投稿