CSVの出力が列のレイアウトが変わるたびに作るのが面倒だったので作りました。
これで簡単なEntityのListオブジェクトをCSVに出力することができます。
プログラム
Imports System.IO.StreamWriter
Imports System.Reflection
Public Class CSVWriter(Of T)
Public Sub SaveEntities(entities As List(Of T), filePath As String, Optional ByVal appendMode As Boolean = False)
Dim writer As IO.StreamWriter
Dim propertyNames As List(Of String)
Dim recodeData As New List(Of String)
writer = New IO.StreamWriter(filePath, appendMode, System.Text.Encoding.GetEncoding("shift_jis"))
'プロパティ名の取得&書き込み
propertyNames = GetPropertyNames(entities.First)
'CSVファイルの1行目に列名を書き込む
writer.WriteLine(String.Join(",", propertyNames.ToArray()))
'値の書き込み
For Each entity In entities
recodeData.Clear()
For Each prop In propertyNames
'スペースやカンマなどを取り込める用に変更する予定
recodeData.Add(GetData(entity, prop))
Next
writer.WriteLine(String.Join(",", recodeData.ToArray()))
Next
writer.Dispose()
End Sub
Private Function GetPropertyNames(entity As T) As List(Of String)
Dim names As New List(Of String)
For Each member In entity.GetType.GetProperties()
names.Add(member.Name)
Next
Return names
End Function
Private Function GetData(entity As T, propertyName As String) As String
Dim result As String
Dim members As PropertyInfo()
Dim member As PropertyInfo
members = entity.GetType.GetProperties
member = members.Where(Function(x) x.Name = propertyName).FirstOrDefault
result = member.GetValue(entity)
Return result
End Function
End Class
使い方
まずは適当に作ったEntityクラスです。
Public Class Ingredient
Property id As Integer
Property Name As String
Property Quantity As String
Public Sub New(ByVal id As Integer, ByVal name As String, ByVal quantity As String)
Me.id = id
Me.Name = name
Me.Quantity = quantity
End Sub
End Class
次に、実際にCSVWriterクラスを実行した例です
Dim recipe As New List(Of Ingredient)
recipe.Add(New Ingredient(1, "米", "1合"))
recipe.Add(New Ingredient(2, "オリーブオイル", "大さじ2"))
recipe.Add(New Ingredient(3, "ブイヨン", "3カップ"))
recipe.Add(New Ingredient(4, "白ワイン", "大さじ1"))
recipe.Add(New Ingredient(5, "バター", "20g"))
recipe.Add(New Ingredient(6, "パルミジャーノ・チーズ", "50g"))
recipe.Add(New Ingredient(7, "塩", "少々"))
recipe.Add(New Ingredient(8, "粗びき黒こしょう", "少々"))
Dim writer As New CSVWriter(Of Ingredient)
writer.SaveEntities(recipe, "C:\Temp\output.csv")
実行するとModule1.vbの13行目で指定したフォルダに「output.csv」というファイル名でcsvファイルが保存されます。
実際にメモ帳などで開くと次のような結果が書き込まれます。
id,Name,Quantity
1,米,1合
2,オリーブオイル,大さじ2
3,ブイヨン,3カップ
4,白ワイン,大さじ1
5,バター,20g
6,パルミジャーノ・チーズ,50g
7,塩,少々
8,粗びき黒こしょう,少々
解説
このクラスのポイントは2つです。
- Genericの利用
- PropetyInfoの利用
これにより、汎用性の高いcsv出力クラスになりました。あとはIngredientのようなEntityクラスを作るだけで様々なcsvファイルを出力することができます。
ただ、コメントでも書いている通りスペースやカンマが入ってしまうとプログラムに読み込むときに失敗します。時間があるときに改良予定。
ステップ毎に何をやっていか知りたいというご要望が、もし仮にある場合は、お問合せで構いませんのでご連絡ください。すぐに作成してアップします。笑
もちろんReaderも作ってます
CSVReaderはこちらを参考にしてください。
コメント