若手エンジニアから「CSVファイルの読み込み方がわからん」と言われたので書きます。最終目的としてはCSVでインポートしたデータをグリッドに表示したいらしいのですが、まずはCSV読み込むところから始めましょう。別に難しい事ではありません。「あなたならできるわ。」
TextFieldParserクラスを使ってCSVファイルを読み込む
そんな難しいことではないので、サクサクと進めます。VB.NETには、TextFieldParserクラスというCSV(カンマ区切り)やTSV(タブ区切り)を扱うためのクラスがあります。このTextFieldParserクラスを使用すれば、アッと驚く為五郎という感じで、あっという間に取り込めます。
実装
理屈は後にして、まずは実際にコーディングしてみましょう。習うより慣れろってやつです。
用意するコントロール
必要なコントロールは4つ。
- フォーム
- テキストボックス1(CSVファイルパスを入れるところ)
- ボタン(CSVインポート実行)
- テキストボックス2(CSV読み込み結果を表示させるところ)
こんな感じで良いでしょう。
ソースコード
ボタンクリックしたら、横に細長いテキストボックスに入力されているCSVファイルパスからCSVファイルを読み込み、下のデカいテキストボックスにCSVファイルの中身を表示するとても簡単なものです。
Imports System.Text Public Class From_CSV_Import Private Sub cmd_CSV_Import_Click(sender As Object, e As EventArgs) Handles cmd_CSV_Import.Click Dim strFilePath As String = Nothing Try strFilePath = txtFilePath.Text '未入力チェック If Trim(strFilePath) = "" Then MessageBox.Show("ファイルパス入れてね!", "未入力", MessageBoxButtons.OK, MessageBoxIcon.Error) Exit Sub End If 'ファイル存在チェック If System.IO.File.Exists(strFilePath) = False Then MessageBox.Show("そんなファイル無いよ!", "未入力", MessageBoxButtons.OK, MessageBoxIcon.Error) Exit Sub End If Using objIoTFP As New Microsoft.VisualBasic.FileIO.TextFieldParser(strFilePath, Encoding.GetEncoding("Shift_JIS")) '読み込み時の設定 With objIoTFP '区切り文字をカンマに設定 .TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited .SetDelimiters(",") '空白があった場合にTrimしない .TrimWhiteSpace = False End With 'CSV読み込み実行 While Not objIoTFP.EndOfData Dim arrayRow As String() = objIoTFP.ReadFields() Dim strVeiwResult As String = Nothing For Each objField As String In arrayRow '表示 strVeiwResult = strVeiwResult & objField & "," Next '列の末尾のカンマを削除 strVeiwResult = strVeiwResult.TrimEnd(",") 'テキストボックスに表示 txtResult.Text = txtResult.Text & strVeiwResult & vbCrLf End While End Using Catch ex As Exception MessageBox.Show(ex.Source.ToString) End Try End Sub End Class
とまあ、こんな感じに書きます。結果はこんな感じ。
はい、簡単ですね。
読み込み時の設定について
読み込み前に設定すれば、色々な読み込み方が出来ます。上記のソースの場合は、
With objIoTFP '区切り文字をカンマに設定 .TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited .SetDelimiters(",") '空白があった場合にTrimしない .TrimWhiteSpace = False End With
- デリミタ(区切り文字)はカンマ
- 空白があった場合にTrim(削除)しない
これだけでした。例えば、タブ区切りの場合は、SetDelimitersメソッドにタブを指定してあげればTSVファイルも読み込めます。
.SetDelimiters(“\t”)
また、フィールドにダブルクォーテーション「””」がある場合(「”いぬ”,”50歳”,”オス”」みたいなデータ)は、HasFieldsEnclosedInQuotesプロパティをTrueに設定すればOKです。
.HasFieldsEnclosedInQuotes = true
他のプロパティやメソッドはMSDNに掲載されていますので、そちらを参照下さい。
Split()を使えば良いのでは?というお言葉に対して…
ええ、それでも良いかもしれません。区切り文字をカンマに指定すれば、配列になって帰って来ます。ただし、CSVに限って言えば、無理にSplit()を使う必要があるのかと思います。物好きな人はSplitを上手い事使ってますが、とても私には真似出来ません。TextFieldParserの方が断然楽です。
理由としては、
- ヘッダ有無の考慮
- ダブルクォーテーションの考慮
があるので、その対応だけで非常に面倒なのです。もっと色々とありますが、取り込むCSVのフォーマットやフィールド値が固定されているのであれば、Split()でも良いかもしれませんが、もっと別のところでSplit()を活躍させてあげるべきなのでは?と思います。
編集後記
とまあこんな感じでCSV読み込めます。とても簡単です。
さて、CSVのフィールド内に改行コードが入っている場合が考えられますが、それはもう諦めましょう。任意入力されたデータをCSVに出力して、それを取り込むというのは、愚行です。
改行コードを考慮してCSVを取り扱う時点で、そのシステム全体を見直した方が良いです。任意入力可能な画面上で改行を禁止する等しておくべきです。
任意入力で改行を許容(というか考慮してない場合が多い)するというのは、「改行コードが混入されたデータを最後まで責任持って面倒見ますよ」と言っているようなものです。そういうシステムに携わったことがありますが、システムの中身や運用体制、メンバーの業務知識のレベルが散々でした。
参考サイト
.