[2019/06/18] DataGridView からCSVファイルへの書込について (No.105)
[2019/06/17] CSVファイルの DataGridView への読込について (No.104)
[2018/08/13] クラスや構造体のそのままのデータをシリアライズ化して保存する方法 (No.52)
[2018/03/22] XMLファイルをINIファイルの様に扱う処理について (No.15)
[2018/03/22] INIファイル読み書き処理 (No.14)
-
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
-
以前の記事でCSVファイルに書込む処理を紹介しましたが、 今回はその関数を利用して DataGridViw コントロールからCSVファイルへのデータ書込みを行います。
⇒CSVファイルの書込について :[System.IO.StreamWriter]
DataGridViw から WriteCsv:CSVファイル書込処理 に指示する文字列配列を作成し、ファイル書込みを行います。 DataGridViw の列ヘッダーからCSVの先頭行のヘッダーデータを取得します。 更に DataGridViw の各行データから、その行のセルデータから文字列配列を作成します。
最初フォームに DataGridView コントロールを配置すると AllowUserToAddRows プロパティが True なので、 DataGridView の最後の行に新規行(*行)が表示される様になります。 (この設定のままで、どんどん新規のデータを入力できます。)
この新規行は何も入力がされていない状態ですので、 CSVファイルにはデータとして登録しない様に DataGridView の行の IsNewRow プロパティが True の場合には 処理しない様にしています。
尚、以下の例ではフォームロードイベント処理で DataGridView の列数を5個として生成を行っています。DataGridView からCSVファイルへの書込
Public Class frmDGV2CSV ' フォームロード時処理 Private Sub frmDGV2CSV_Load(sender As Object, e As EventArgs) Handles Me.Load Try 'DataGridView列数を5に固定 Dim arrColName() As String = {"COL1", "COL2", "COL3", "COL4", "COL5"} For Each strName As String In arrColName Me.dgv.Columns.Add(strName, strName) Next Catch ex As Exception 'エラー MsgBox(ex.Message) End Try End Sub ' [WriteCSV From DataGridView]ボタンクリック処理 Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Try 'DataGridViewからCSVファイルへの書込処理の呼出 If WriteCsvFromDGV(Me.dgv, "testw.csv") = True Then MsgBox("CSVファイル書込・正常") Else MsgBox("CSVファイル書込・エラー") End If Catch ex As Exception 'エラー MsgBox(ex.Message) End Try End Sub ''' ----------------------------------------------------------------------------- ''' <summary> ''' DataGridViewからCSVファイルへの書込処理 ''' (WriteCsv:CSVファイルの書込処理の利用による) ''' </summary> ''' <param name="dgv">DataGridView</param> ''' <param name="astrFileName">ファイル名</param> ''' ----------------------------------------------------------------------------- Private Function WriteCsvFromDGV(ByVal dgv As DataGridView, ByVal astrFileName As String) As Boolean WriteCsvFromDGV = False Try 'DataGridView全体のデータ領域 Dim arrData()() As String = Nothing '1行分を読込 Dim arrHead As String() = Nothing '列ヘッダの名称取得 For col As Integer = 0 To Me.dgv.Columns.Count - 1 '1列分の領域拡張 ReDim Preserve arrHead(col) '列のヘッダデータ退避 arrHead(col) = CStr(Me.dgv.Columns(col).HeaderCell.Value) Next '1行分の領域拡張 ReDim Preserve arrData(0) '列ヘッダ名退避 arrData(0) = arrHead 'データ行数分の処理 For row As Integer = 0 To Me.dgv.Rows.Count - 1 '新規行は処理しない If Me.dgv.Rows(row).IsNewRow Then Continue For End If '1行分を読込 Dim arrLine As String() = Nothing '列数分の処理 For col As Integer = 0 To Me.dgv.Columns.Count - 1 '1列分の領域拡張 ReDim Preserve arrLine(col) '列データ退避 arrLine(col) = CStr(Me.dgv.Rows(row).Cells(col).Value) Next '1行分の領域拡張 ReDim Preserve arrData(row + 1) '1行データ退避 arrData(row + 1) = arrLine Next '実際のCSVファイルの書込み Return WriteCsv(astrFileName, arrData) Catch ex As Exception 'エラー MsgBox(ex.Message) End Try End Function ''' ----------------------------------------------------------------------------- ''' <summary> ''' CSVファイルの書込処理 ''' </summary> ''' <param name="astrFileName">ファイル名</param> ''' <param name="aarrData">書込データ文字列の2次元配列</param> ''' <returns>True:結果OK, False:NG</returns> ''' <remarks>カラム名をファイルに出力したい場合は、書込データの先頭に設定すること</remarks> ''' ----------------------------------------------------------------------------- Private Function WriteCsv(ByVal astrFileName As String, ByVal aarrData As String()()) As Boolean WriteCsv = False 'ファイルStreamWriter Dim sw As System.IO.StreamWriter = Nothing Try 'CSVファイルに書込に使うEncoding Dim enc As System.Text.Encoding = System.Text.Encoding.GetEncoding("Shift_JIS") '書き込むファイルを開く sw = New System.IO.StreamWriter(astrFileName, False, enc) For Each arrLine() As String In aarrData Dim blnFirst As Boolean = True Dim strLIne As String = "" For Each str As String In arrLine If blnFirst = False Then '「,」(カンマ)の書込 sw.Write(",") End If blnFirst = False '1カラムデータの書込 str = """" & str & """" sw.Write(str) Next '改行の書込 sw.Write(vbCrLf) Next '正常終了 Return True Catch ex As Exception 'エラー MsgBox(ex.Message) Finally '閉じる If sw IsNot Nothing Then sw.Close() End If End Try End Function End Class
DataGridView にデータを入力したところのフォームの表示は以下の様になります。
[WriteCSV From DataGridView] ボタンを押下すると以下の様なCSVファイルが書き込まれます。
CSVファイルの内容
"COL1","COL2","COL3","COL4","COL5" "111","22222","33333","4444","55555" "aaa","bbb","cccccc","ddd","ee" "AAA","22","CCCCC","DDDD","EEE"
関連する記事
⇒CSVファイルの読込について :[Microsoft.VisualBasic.FileIO.TextFieldParser]
⇒CSVファイルの書込について :[System.IO.StreamWriter]
⇒CSVファイルの DataGridView への読込について
PR -
以前の記事でCSVファイルを読込む処理を紹介しましたが、 今回はその関数を利用して DataGridViw コントロールへのデータ設定を行います。
⇒CSVファイルの読込について :[Microsoft.VisualBasic.FileIO.TextFieldParser]
DataGridViw への設定では ReadCsv:CSVファイル読込処理 から返された文字列配列を基に、各カラムに文字列として設定を行います。 DataGridViw は列が無いと対象セルへの設定ができないので、 ReadCsv 処理後最初に先頭行の列数を設定します。また、各行の設定の前で列数の変化があれば拡張を行っています。CSVファイルの DataGridView への読込
Imports Microsoft.VisualBasic.FileIO Public Class frmCSV2DGV ''' ----------------------------------------------------------------------------- ''' <summary> ''' CSVファイルの読込処理 ''' </summary> ''' <param name="astrFileName">ファイル名</param> ''' <param name="ablnTab">区切りの指定(True:タブ区切り, False:カンマ区切り)</param> ''' <param name="ablnQuote">引用符フラグ(True:引用符で囲まれている, False:囲まれていない)</param> ''' <returns>読込結果の文字列の2次元配列</returns> ''' ----------------------------------------------------------------------------- Private Function ReadCsv(ByVal astrFileName As String, ByVal ablnTab As Boolean, ByVal ablnQuote As Boolean) As String()() ReadCsv = Nothing 'ファイルStreamReader Dim parser As Microsoft.VisualBasic.FileIO.TextFieldParser = Nothing Try 'Shift-JISエンコードで変換できない場合は「?」文字の設定 Dim encFallBack As System.Text.DecoderReplacementFallback = _ New System.Text.DecoderReplacementFallback("?") Dim enc As System.Text.Encoding = System.Text.Encoding.GetEncoding("shift_jis", _ System.Text.EncoderFallback.ReplacementFallback, encFallBack) 'TextFieldParserクラス parser = New Microsoft.VisualBasic.FileIO.TextFieldParser(astrFileName, enc) '区切りの指定 parser.TextFieldType = FieldType.Delimited If ablnTab = False Then 'カンマ区切り parser.SetDelimiters(",") Else 'タブ区切り parser.SetDelimiters(vbTab) End If If ablnQuote = True Then 'フィールドが引用符で囲まれているか parser.HasFieldsEnclosedInQuotes = True End If 'フィールドの空白トリム設定 parser.TrimWhiteSpace = False Dim strArr()() As String = Nothing Dim nLine As Integer = 0 'ファイルの終端までループ While Not parser.EndOfData 'フィールドを読込 Dim strDataArr As String() = parser.ReadFields() '戻り値領域の拡張 ReDim Preserve strArr(nLine) '退避 strArr(nLine) = strDataArr nLine += 1 End While '正常終了 Return strArr Catch ex As Exception 'エラー MsgBox(ex.Message) Finally '閉じる If parser IsNot Nothing Then parser.Close() End If End Try End Function ''' ----------------------------------------------------------------------------- ''' <summary> ''' CSVファイルのDataGridViewへの読込処理 ''' (ReadCsv:CSVファイルの読込処理の利用による) ''' </summary> ''' <param name="dgv">DataGridView</param> ''' <param name="astrFileName">ファイル名</param> ''' <param name="ablnTab">区切りの指定(True:タブ区切り, False:カンマ区切り)</param> ''' <param name="ablnQuote">引用符フラグ(True:引用符で囲まれている, False:囲まれていない)</param> ''' ----------------------------------------------------------------------------- Private Sub ReadCsvToDGV(ByVal dgv As DataGridView, ByVal astrFileName As String, Optional ByVal ablnTab As Boolean = False, Optional ByVal ablnQuote As Boolean = False) Try 'CSVファイル読込処理 Dim arrCsv()() As String = ReadCsv(astrFileName, ablnTab, ablnQuote) 'DataGridView クリア dgv.Rows.Clear() '列数の設定 dgv.ColumnCount = arrCsv(0).Length Dim row As Integer = 0 For Each arr In arrCsv 'DataGridView 新規行を追加 dgv.Rows.Add() 'DataGridViewの列数がデータ配列数より小さい場合は列拡張 If dgv.ColumnCount < arr.Length Then dgv.ColumnCount = arr.Length End If For col As Integer = 0 To arr.Length - 1 'セルに列、行を指定して値の設定 dgv(col, row).Value = arr(col) Next '次の行へ row += 1 Next Catch ex As Exception 'エラー MsgBox(ex.Message) End Try End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 'CSVファイルをDataGridViewへ読込処理 ReadCsvToDGV(Me.DataGridView1, "test2.csv") End Sub End Class
以下の様なCSVファイルを読込みます。CSVファイルの内容
TEST1,TEST2,TEST3 1000,2000,3000 aaaa,bbbb,cccc,dddd 000,111,4444,55555,6666 AAAAAAA,BBBBB
読込んだフォームの表示は以下の様になります。
この場合 DataGridViw の列ヘッダに設定はしていませんので、CSVファイルの先頭行にヘッダが存在する場合を考慮した 読込関数を以下に記します。DataGridViw への設定関数と実行例の部分のみを抜粋しています。CSVファイルの DataGridView への読込2
''' ----------------------------------------------------------------------------- ''' <summary> ''' CSVファイルのDataGridViewへの読込処理 ''' (ReadCsv:CSVファイルの読込処理の利用による) ''' </summary> ''' <param name="dgv">DataGridView</param> ''' <param name="astrFileName">ファイル名</param> ''' <param name="ablnTab">区切りの指定(True:タブ区切り, False:カンマ区切り)</param> ''' <param name="ablnQuote">引用符フラグ(True:引用符で囲まれている, False:囲まれていない)</param> ''' <param name="ablnHeader">先頭行が列ヘッダ</param> ''' <param name="ablnExtendColumn">列数の拡張を行う指示</param> ''' ----------------------------------------------------------------------------- Private Sub ReadCsvToDGV(ByVal dgv As DataGridView, ByVal astrFileName As String, Optional ByVal ablnTab As Boolean = False, Optional ByVal ablnQuote As Boolean = False, Optional ByVal ablnHeader As Boolean = False, Optional ByVal ablnExtendColumn As Boolean = True) Try 'CSVファイル読込処理 Dim arrCsv()() As String = ReadCsv(astrFileName, ablnTab, ablnQuote) 'DataGridView クリア dgv.Rows.Clear() Dim row As Integer = 0 Dim blnFirst As Boolean = True For Each arr In arrCsv If blnFirst = True Then blnFirst = False If ablnHeader = True Then '先頭行が列ヘッダの場合 dgv.Columns.Clear() For Each strColName In arr dgv.Columns.Add(strColName, strColName) Next Continue For Else '列数の設定 dgv.ColumnCount = arrCsv(0).Length End If End If 'DataGridView 新規行を追加 dgv.Rows.Add() 'DataGridViewの列数がデータ配列数より小さい場合は列拡張 If ablnExtendColumn = True And dgv.ColumnCount < arr.Length Then dgv.ColumnCount = arr.Length End If For col As Integer = 0 To arr.Length - 1 If col >= dgv.Columns.Count Then Exit For End If 'セルに列、行を指定して値の設定 dgv(col, row).Value = arr(col) Next '次の行へ row += 1 Next Catch ex As Exception 'エラー MsgBox(ex.Message) End Try End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 'CSVファイルをDataGridViewへ読込処理:先頭行が列ヘッダで列数拡張 ReadCsvToDGV(Me.DataGridView1, "test2.csv", False, False, True, True) MsgBox("OK") 'CSVファイルをDataGridViewへ読込処理:先頭行が列ヘッダで列数拡張無し ReadCsvToDGV(Me.DataGridView1, "test2.csv", False, False, True, False) End Sub
実行結果(先頭行が列ヘッダで列数拡張)は以下の様になります。
メッセージ表示後(先頭行が列ヘッダで列数拡張無し)の表示は以下の様になります。
関連する記事
⇒CSVファイルの読込について :[Microsoft.VisualBasic.FileIO.TextFieldParser]
⇒CSVファイルの書込について :[System.IO.StreamWriter]
⇒DataGridView からCSVファイルへの書込について
-
クラスや構造体のデータをそのままファイルに登録し、再度読み込んで利用したい場合があります。 この様な時に、クラスや構造体をそのままシリアライズ化し、バイナリ形式でファイルに書き込むことでできます。
今回は簡単な例として、クラスは3個のパブリックな要素を持っています。 このクラスにデータを書込むときには、3個の変数にデータを設定してから、 バイナリファイルへの書込関数と、バイナリファイルからの読込関数を呼出しています。 但し、クラスの宣言には <Serializable()> が必要です。
バイナリファイルへの書込関数では、指定されたファイルを FileStream クラスで生成オープンして、 BinaryFormatter クラスでシリアライズ化を行って書き込みます。
バイナリファイルからの読込関数でも、同様に指定されたファイルを FileStream クラスでオープンして、 BinaryFormatter クラスでストリームからのデータを逆シリアライズ化を行って読み込みます。
尚、この例を示すために、3個のボタンを貼り、テストの実行を行います。クラスや構造体のそのままのデータをシリアライズ化して保存する方法
Public Class frmSerialize '''
''' シリアライズ化を行うクラス(仮のクラス) ''' <Serializable()> _ Public Class DataClass Public intNo As Integer '番号 Public strData1 As String 'データ1 Public strData2 As String 'データ2 End Class '''''' シリアライズ化関数 ''' ''' <param name="strFileName">書込みファイル名</param> ''' <param name="objPara">シリアライズ化するオブジェクト</param> '''True:OK、False:NG Public Function WriteObj(ByVal strFileName As String, ByVal objPara As Object) As Boolean '指定されたファイルをFileStreamクラスで生成オープン Dim fs As New System.IO.FileStream(strFileName, System.IO.FileMode.Create) 'BinaryFormatterクラス(オブジェクトのバイナリ形式でシリアル化および逆シリアル化クラス) Dim bf As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter Try 'オブジェクトをバイナリ形式でシリアル化 bf.Serialize(fs, objPara) Return True Catch ex As Runtime.Serialization.SerializationException Return False Finally fs.Close() End Try End Function '''''' デシリアライズ関数 ''' ''' <param name="strFileName">読込みファイル名</param> ''' <param name="objPara">結果を返すオブジェクト</param> '''True:OK、False:NG Public Function ReadObj(ByVal strFileName As String, ByRef objPara As Object) As Boolean '指定されたファイルをFileStreamクラスでオープン Dim fs As New System.IO.FileStream(strFileName, System.IO.FileMode.Open) 'BinaryFormatterクラス(オブジェクトのバイナリ形式でシリアル化および逆シリアル化クラス) Dim bf As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter Try '指定されたオブジェクトを逆シリアル化し、指定オブジェクトに返す objPara = bf.Deserialize(fs) Return True Catch ex As Runtime.Serialization.SerializationException Return False Finally fs.Close() End Try End Function ' ***** これ以降は上記の関数等をテストするボタン処理 ***** ' [シリアライズ化]ボタン処理 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 'クラスのインスタンス宣言 Dim dc As New DataClass 'クラスにデータ設定 dc.intNo = TextBox1.Text dc.strData1 = TextBox2.Text dc.strData2 = TextBox3.Text 'シリアライズ化(ファイルはデフォルトの位置) Dim blnRet As Boolean = WriteObj("DataFile.dat", dc) End Sub ' [逆シリアライズ化]ボタン処理 Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim obj As Object = Nothing Dim blnRet As Boolean = ReadObj("DataFile.dat", obj) If blnRet = True Then Dim dc As DataClass = DirectCast(obj, DataClass) TextBox1.Text = dc.intNo TextBox2.Text = dc.strData1 TextBox3.Text = dc.strData2 End If End Sub Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click TextBox1.Text = "" TextBox2.Text = "" TextBox3.Text = "" End Sub End Class
結果これを実行すると以下の様になります。関連する記事
⇒バイト配列を介したバイナリファイルの読込・書込処理について
-
INIファイルは簡単にプログラムの動作パラメータなどを保存しておくには便利な機能です。 この機能をXMLファイルで出来る様にクラスを作成してみました。
INIファイルへの書込み、読み込みの様な関数を持ったクラスになります。 以下にそのクラスのソースを示します。XMLファイルをINIファイルの様に読み書きクラス
Imports System.Xml Imports System.Text Public Class ClsXmlIni Private XmlDoc As XmlDocument Private XmlFileName As String '''
''' コンストラクタ ''' ''' <param name="strXmlFilePath">XMLファイル</param> Public Sub New(ByVal strXmlFilePath As String) Try '初期XMLファイル読込 Me.XmlFileName = strXmlFilePath Me.XmlDoc = New XmlDocument If System.IO.File.Exists(strXmlFilePath) = False Then 'XML宣言を設定する Dim xmlDecl As System.Xml.XmlDeclaration = XmlDoc.CreateXmlDeclaration("1.0", "Shift-JIS", Nothing) '作成したXML宣言をDOMドキュメントに追加します XmlDoc.AppendChild(xmlDecl) Else 'ファイルが存在した場合 XmlDoc.Load(strXmlFilePath) 'XMLファイルをロード End If Catch ex As Exception Throw ex End Try End Sub '''''' プロファイル文字列の取得 ''' ''' <param name="strAppName">アプリケーション文字列</param> ''' <param name="strKeyName">キー文字列</param> ''' <param name="strDefault">デフォルト文字列</param> ''' <returns>プロファイル文字列</returns> Public Function GetProfileString(ByVal strAppName As String, _ ByVal strKeyName As String, _ ByVal strDefault As String) As String '戻り値初期化 GetProfileString = strDefault Try '引数チェック If strAppName = "" Or strKeyName = "" Then Exit Function 'INIノードチェック Dim xeleIni As XmlElement = Me.XmlDoc.SelectSingleNode("INI") If Not xeleIni Is Nothing Then 'APPチェック Dim xeleApp As XmlElement = xeleIni.SelectSingleNode(strAppName) If Not xeleApp Is Nothing Then 'KEYチェック Dim xeleKey As XmlElement = xeleApp.SelectSingleNode(strKeyName) If Not xeleKey Is Nothing Then GetProfileString = xeleKey.InnerText End If End If End If Catch ex As Exception Throw ex End Try End Function '''''' プロファイル文字列設定 ''' ''' <param name="strAppName">アプリケーション文字列</param> ''' <param name="strKeyName">キー文字列</param> ''' <param name="strSet">設定文字列</param> ''' <returns>True:正常, False:エラー</returns> Public Function WriteProfileString(ByVal strAppName As String, _ ByVal strKeyName As String, _ ByVal strSet As String) As Boolean '戻り値初期化 WriteProfileString = False Try '引数チェック If strAppName = "" Or strKeyName = "" Then Exit Function 'INIノードチェック Dim xeleIni As XmlElement = Me.XmlDoc.SelectSingleNode("INI") If xeleIni Is Nothing Then xeleIni = Me.XmlDoc.CreateElement("INI") 'INI要素を作成 Call Me.XmlDoc.AppendChild(xeleIni) 'ドキュメントに追加 End If 'APPチェック Dim xeleApp As XmlElement = xeleIni.SelectSingleNode(strAppName) If xeleApp Is Nothing Then xeleApp = Me.XmlDoc.CreateElement(strAppName) 'APP要素を作成 Call xeleIni.AppendChild(xeleApp) 'INI要素に追加 End If 'KEYチェック Dim xeleKey As XmlElement = xeleApp.SelectSingleNode(strKeyName) If xeleKey Is Nothing Then xeleKey = Me.XmlDoc.CreateElement(strKeyName) 'KEY要素を作成 Dim xValKey As XmlText = Me.XmlDoc.CreateTextNode(strSet) '設定値を作成 Call xeleKey.AppendChild(xValKey) 'KEY要素に値を追加 Call xeleApp.AppendChild(xeleKey) 'APP要素に追加 Else 'KEYが存在 xeleKey.InnerText = strSet End If 'XMLファイルの上書き Me.XmlDoc.Save(Me.XmlFileName) Return True Catch ex As Exception Return False End Try End Function End Classこのクラスを利用する例を以下に記します。 フォーム(frmXmlIni)の上にボタンを貼り付け、このボタン処理内で、 最初にXMLファイルへの書込を行い、その後でそのXMLファイルからの読込を行っています。 その後さらに、書込と読込を行っています。
Public Class frmXmlIni Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Try 'XMLファイルのテスト Dim strPath As String = System.IO.Path.GetDirectoryName(Application.ExecutablePath) Dim Ini As New ClsXmlIni(strPath & "\TEST.XML") '書込テスト Ini.WriteProfileString("SECTION1", "DATA1", "aaa") Ini.WriteProfileString("SECTION1", "DATA2", "bbb") Ini.WriteProfileString("SECTION2", "DATA1", "AAA") '読込テスト Dim strDsp As String = "" strDsp &= "SECTION1:DATA1=" & Ini.GetProfileString("SECTION1", "DATA1", "***") & vbCrLf strDsp &= "SECTION1:DATA1=" & Ini.GetProfileString("SECTION1", "DATA2", "") & vbCrLf strDsp &= "SECTION1:DATA1=" & Ini.GetProfileString("SECTION2", "DATA1", "@@@") & vbCrLf MsgBox(strDsp) '書込テスト Ini.WriteProfileString("SECTION1", "DATA1", "111") Ini.WriteProfileString("SECTION1", "DATA2", "222") Ini.WriteProfileString("SECTION2", "DATA1", "333") '読込テスト strDsp = "" strDsp &= "SECTION1:DATA1=" & Ini.GetProfileString("SECTION1", "DATA1", "") & vbCrLf strDsp &= "SECTION1:DATA1=" & Ini.GetProfileString("SECTION1", "DATA2", "") & vbCrLf strDsp &= "SECTION1:DATA1=" & Ini.GetProfileString("SECTION2", "DATA1", "") & vbCrLf MsgBox(strDsp) Catch ex As Exception MsgBox(ex.Message) End Try End Sub End Class
この処理の後のXMLファイルの内容は以下の様になります。
<?xml version="1.0" encoding="Shift-JIS"?> <INI> <SECTION1> <DATA1>111</DATA1> <DATA2>222</DATA2> </SECTION1> <SECTION2> <DATA1>333</DATA1> </SECTION2> </INI>
-
INIファイルというと今更感がありますが、 簡単にプログラムの動作パラメータなどを保存しておくには便利な機能です。 私もプログラムの変更なしに、外からタイミングの時間の値を後から少し変えたい場合によく使います。
INIファイルの構造は以下の様になります。[SECTION1] KEY1=keydata1 KEY2=keydata2 [SECTION2] KEYA=keydataA ...
■セクション
[ ] で囲まれた部分がセクションで、各セクションの中にキー文字列を宣言します。
■キー
各セクションの中に宣言される文字列で、その値を = で定義します。
セクションが異なれば、同じキーが在ってもOKです。
■コメント
先頭に ;(セミコロン) を置くとその行はコメント行とみなされます。
また、行の途中に ;(セミコロン) が在ると、それ以降はコメントであるとみなされます。
■エスケープシーケンス
キーの値の文字列として ;(セミコロン) :(コロン) =(等号) #(シャープ) の各文字を含めたい場合があります。その時には各文字の前に \(円マーク) を置きエスケープしてやります。
(以下のソースのクラスではエスケープシーケンスの設定と解除を関数化しています)
以下にINIファイルを取り扱うクラスのソースを示します。INIファイル読み書きクラス
Imports System.Text Imports System.Runtime.InteropServices Public Class ClsIni 'プロファイル文字列取得 'Private Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" ( _ ' ByVal lpApplicationName As String, _ ' ByVal lpKeyName As String, _ ' ByVal lpDefault As String, _ ' ByVal lpReturnedString As System.Text.StringBuilder, _ ' ByVal nSize As UInt32, _ ' ByVal lpFileName As String) As UInt32 '宣言修正 Private Declare Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" ( _ <MarshalAs(UnmanagedType.LPStr)> ByVal lpApplicationName As String, _ <MarshalAs(UnmanagedType.LPStr)> ByVal lpKeyName As String, _ <MarshalAs(UnmanagedType.LPStr)> ByVal lpDefault As String, _ <MarshalAs(UnmanagedType.LPStr)> ByVal lpReturnedString As StringBuilder, _ ByVal nSize As UInt32, _ <MarshalAs(UnmanagedType.LPStr)> ByVal lpFileName As String) As UInt32 'プロファイル文字列書込み 'Private Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" ( _ ' ByVal lpAppName As String, _ ' ByVal lpKeyName As String, _ ' ByVal lpString As String, _ ' ByVal lpFileName As String) As Integer '宣言修正 Private Declare Function WritePrivateProfileString Lib "kernel32" Alias "WritePrivateProfileStringA" ( _ <MarshalAs(UnmanagedType.LPStr)> ByVal lpAppName As String, _ <MarshalAs(UnmanagedType.LPStr)> ByVal lpKeyName As String, _ <MarshalAs(UnmanagedType.LPStr)> ByVal lpString As String, _ <MarshalAs(UnmanagedType.LPStr)> ByVal lpFileName As String) As Integer Private strIniFileName As String = "" '''
''' コンストラクタ ''' ''' <param name="strIniFile">INIファイル名(フルパス)</param> Sub New(ByVal strIniFile As String) Me.strIniFileName = strIniFile 'ファイル名退避 End Sub '''''' プロファイル文字列取得 ''' ''' <param name="strAppName">アプリケーション文字列</param> ''' <param name="strKeyName">キー文字列</param> ''' <param name="strDefault">デフォルト文字列</param> '''プロファイル文字列 Public Function GetProfileString(ByVal strAppName As String, _ ByVal strKeyName As String, _ ByVal strDefault As String) As String Try Dim strWork As System.Text.StringBuilder = New System.Text.StringBuilder(1024) Dim intRet As Integer = GetPrivateProfileString(strAppName, strKeyName, strDefault, strWork, strWork.Capacity - 1, strIniFileName) If intRet > 0 Then 'エスケープ文字を解除して返す Return ResetEscape(strWork.ToString()) Else Return strDefault End If Catch ex As Exception Return strDefault End Try End Function '''''' プロファイル文字列設定 ''' ''' <param name="strAppName">アプリケーション文字列</param> ''' <param name="strKeyName">キー文字列</param> ''' <param name="strSet">設定文字列</param> '''True:正常, False:エラー Public Function WriteProfileString(ByVal strAppName As String, _ ByVal strKeyName As String, _ ByVal strSet As String) As Boolean Try 'エスケープ文字変換 Dim strCnv As String = SetEscape(strSet) Dim intRet As Integer = WritePrivateProfileString(strAppName, strKeyName, strCnv, strIniFileName) If intRet > 0 Then Return True Else Return False End If Catch ex As Exception Return False End Try End Function '''''' エスケープ文字変換 ''' ''' <param name="strSet">設定文字列</param> '''変換後文字列 Private Function SetEscape(ByVal strSet As String) As String Dim strEscape As String = ";#=:" Dim strRet As String = strSet Try For i = 0 To strEscape.Length - 1 Dim str As String = strEscape.Substring(i, 1) strRet = strRet.Replace(str, "\" & str) Next Return strRet Catch ex As Exception Return "" End Try End Function '''''' エスケープ文字解除 ''' ''' <param name="strSet">設定文字列</param> '''変換後文字列 Private Function ResetEscape(ByVal strSet As String) As String Dim strEscape As String = ";#=:" Dim strRet As String = strSet Try For i = 0 To strEscape.Length - 1 Dim str As String = strEscape.Substring(i, 1) strRet = strRet.Replace("\" & str, str) Next Return strRet Catch ex As Exception Return "" End Try End Function End Class
このクラスを利用する例を以下に記します。 このボタン処理内では、最初にINIファイルへの書き込みを行い、その後でそのINIファイルからの読込を行っています。
Private Sub ButtonIni_Click(sender As Object, e As EventArgs) Handles ButtonIni.Click '自分自身の存在するフォルダ Dim strPath As String = System.IO.Path.GetDirectoryName(Application.ExecutablePath) 'INIファイルクラスの生成 Dim Ini As New ClsIni(strPath & "\TEST.INI") 'INIファイルへの書込みテスト Ini.WriteProfileString("SECTION1", "DATA1", "test-data-1:aaa") Ini.WriteProfileString("SECTION1", "DATA2", "test-data-2;bbb") Ini.WriteProfileString("SECTION2", "DATA1", "TEST-DATA-1=:;#AAA") 'INIファイルからの取得テスト Dim str As String str = Ini.GetProfileString("SECTION1", "DATA1", "default-data-1:aaa") Console.WriteLine("SECTION1:DATA1=" & str) str = Ini.GetProfileString("SECTION1", "DATA2", "default-data-2;bbb") Console.WriteLine("SECTION1:DATA2=" & str) str = Ini.GetProfileString("SECTION2", "DATA1", "default-DATA-1=:;#AAA") Console.WriteLine("SECTION2:DATA1=" & str) str = Console.ReadLine() End Sub
INIファイルへの書込みでエスケープしないといけない文字を含んでいますので、 このプログラムを実行し「TEST.INI」をテキストエディタで確認すると、 \(円マーク) が付加されて書き込まれているのがわかるはずです。
関連する記事
⇒XMLファイルをINIファイルの様に扱う処理:[XmlDocument,XmlElement,CreateElement]
おすすめ本