背景
プロパティのまとまったクラスを使用し、CSV出力をしたいが、
プロパティ名を全て記載してCSV出力のためのファイルを作るのは手間がかかるし、
1つ追加する度にソースの変更が発生してしまう。
ということで、プロパティに順番のカスタム属性を付与し、
その順番順にForeachで繰り返すことでプロパティの値を取得するソースを作成しました。
目次
ソースコード全文は以下の通りです。
ソースコードの解説について記載しています。
ソースコード
Propertyクラス
''' <summary>
''' CSV用項目
''' </summary>
Public Class CsvProperty
' ヘッダー区分
<Sort(0)>
Property HeaderKbn As String
' ID
<Sort(1)>
Property Id As Integer
' 項目1
<Sort(2)>
Property Item1 As String
' 項目2
<Sort(3)>
Property Item2 As String
' 項目3
<Sort(4)>
Property Item3 As String
End Class
カスタム属性クラス
''' <summary>
''' カスタム属性
''' </summary>
<AttributeUsage(AttributeTargets.Property, AllowMultiple:=False, Inherited:=False)>
Public Class SortAttribute
Inherits Attribute
Private index As Integer
Public Sub New(prmIndex As Integer)
index = prmIndex
End Sub
Public ReadOnly Property SortIndex As Integer
Get
Return index
End Get
End Property
End Class
メイン
''' <summary>
''' メイン
''' </summary>
Public Shared Sub Main()
' テストデータ作成
Dim csvList As New List(Of CsvProperty)
Dim csvItems1 As New CsvProperty
csvItems1.HeaderKbn = "H"
csvItems1.Id = 1
csvItems1.Item1 = "テスト項目1-1"
csvItems1.Item2 = "テスト項目1-2"
csvItems1.Item3 = "テスト項目1-3"
csvList.Add(csvItems1)
Dim csvItems2 As New CsvProperty
csvItems2.HeaderKbn = "D"
csvItems2.Id = 2
csvItems2.Item1 = "テスト項目2-1"
csvItems2.Item2 = "テスト項目2-2"
csvItems2.Item3 = "テスト項目2-3"
csvList.Add(csvItems2)
Dim csvFilePath As String = "C:\CSV\CSVプロパティカスタム.csv"
If IO.File.Exists(csvFilePath) Then
' 同名ファイルが既に存在する場合、削除
IO.File.Delete(csvFilePath)
End If
' CSVファイル書き込み
Dim csvFile As New System.IO.StreamWriter(csvFilePath, True, Text.Encoding.GetEncoding("Shift_JIS"))
' CSV出力順にリスト作成
Dim sortCsvList As List(Of String) =
GetType(CsvProperty).GetProperties().
OrderBy(Function(a) CType(Attribute.GetCustomAttribute(a, GetType(SortAttribute)), SortAttribute).SortIndex).
Select(Function(a) a.Name).
ToList()
' テストデータのリスト数分繰り返す
For Each csvItems As CsvProperty In csvList
Dim lastCnt As Integer = sortCsvList.Count
Dim cnt As Integer = 0
' csv項目数分繰り返す
For Each sortCsvItem As String In sortCsvList
csvFile.Write("""" & CallByName(csvItems, sortCsvItem, CallType.Get) & """")
If lastCnt - 1 > cnt Then
csvFile.Write(","c)
End If
cnt += 1
Next
' 改行する
csvFile.Write(vbCrLf)
Next
' CSVファイル書き込み終了
csvFile.Close()
End Sub
出力CSV

ソースコードの詳細
Propertyクラス
<Sort(0)>
Property HeaderKbn As String
- <Sort(X)>がカスタム属性
- <SortAttribute(X)>でも記載できる
カスタム属性クラス
<AttributeUsage(AttributeTargets.Property, AllowMultiple:=False, Inherited:=False)>
- AttributeUsage
- カスタム属性の適用方法を制御できる属性
- AllowMultiple
- カスタム属性が複数回適用できる(TRUE)か、できない(FALSE)を指定できる
- Inherited
- カスタム属性から派生するクラスを継承する(TRUE)か、しない(FALSE)を指定できる
Public Class SortAttribute
Inherits Attribute
Private index As Integer
Public Sub New(prmIndex As Integer)
index = prmIndex
End Sub
Public ReadOnly Property SortIndex As Integer
Get
Return index
End Get
End Property
End Class
- <Sort(X)>のXの値がSETされ、SortIndexでGETできる
メイン
' CSV出力順にリスト作成
Dim sortCsvList As List(Of String) =
GetType(CsvProperty).GetProperties().
OrderBy(Function(a) CType(Attribute.GetCustomAttribute(a, GetType(SortAttribute)), SortAttribute).SortIndex).
Select(Function(a) a.Name).
ToList()
- SortIndex順にPropertyクラスを並び替える
- プロパティ名だけのリストを作成する
csvFile.Write("""" & CallByName(csvItems, sortCsvItem, CallType.Get) & """")