INIファイルとは
VBAでも外部の設定ファイルを利用したい場合があります。その場合に利用される1つの方法がINIファイルです。
Microsoftは設定内容の保存はINIファイルではなくレジストリやXMLファイルを使うことを推奨していますが、今でもINIファイルは多くの開発現場で利用されています。
INIファイルはShift-JISで書かれたただのテキストファイルですが、WindowsにおけるINIファイルは一般的に以下のような構成をします。
1 2 3 |
; セミコロン以降はコメント [Section] key=value |
- GetPrivateProfileString関数を利用する場合は、INIファイルの文字コードはShift-JISである必要があります。文字コードがUTF-8など場合は設定値に全角文字が含まれている場合、取得した値が文字化けを起こします。
- Sectionは[]で囲まれている必要があります。
- 次のSectionが定義されるまでのkeyとvalueは直前のSectionに所属しているとみなされます。
- Sectionが異なっていればkey名は重複しても構いません。
- valueの値が半角スペースで終わっている場合、後述するGetPrivateProfileString関数で取得した場合、半角スペースを除いた値を取得します。
INIファイルの例
1 2 3 4 5 6 7 8 9 10 11 12 |
;//------------------------------------------ ;// ファイル名:tcp.ini ;// 内容 :TCP処理に必要な設定を保持する ;//------------------------------------------ ;// TCPサーバ情報 [TCP_SERVER] IP=192.168.20.1 PORT=12345 ;// TCPクライアント情報 [TCP_CLIENT] IP=192.168.11.5 PORT=50005 |
指定キーの値をGetPrivateProfileString関数で取得する
通常、テキストファイルの内容を取得するにはFileSystemObjectクラスやOpenTextメソッドを利用して、1行ずつ内容を判定しながら取得する、という流れになりますが、上記のINIファイルの形式を守っている場合はWin32APIのGetPrivateProfileString関数を利用することでファイル操作の処理を行わずに指定したキーの値を取得することが可能です。
GetPrivateProfileString関数の機能
GetPrivateProfileString関数はINIファイル内で第一引数のlpApplicationNameパラメータで指定されたセクション以降にある第二引数のlpKeyNameパラメータで指定された名前に一致するキーを検索します。
キーが見つかった場合、そのキーに対応する文字列を第四引数に取得値として設定します。
キーが見つからなかった場合は第三引数のlpDefaultパラメータで指定された既定の文字列を第四引数の取得値として設定します。
構文は以下の通りです。Declareステートメント等はサンプルコードをご参照ください。
1 2 3 4 5 6 7 8 |
Function GetPrivateProfileString( _ ByVal lpApplicationName As String, _ ByVal lpKeyName As Any, _ ByVal lpDefault As String, _ ByVal lpReturnedString As String, _ ByVal nSize As Long, _ ByVal lpFileName As String ) As Long |
lpApplicationName | セクション文字列を指定します。 |
lpKeyName | キー文字列を指定します。 |
lpDefault | キー文字列が見つからなかった場合の代替値を文字列で指定します。 |
lpReturnedString | キー文字列に対応する値が設定されます。
事前に値の文字列が格納できるサイズまで拡張しておく必要があります。 値の文字列長の方が大きい場合は、事前に拡張したサイズまでしか取得できません。 |
nSize | lpReturnedStringパラメータのサイズを指定します。 |
lpFileName | INIファイルのパスを指定します。 |
戻り値 | 取得した文字列のバイト数をShift-JIS換算(半角は1、全角は2として)返します。 |
サンプルコード
上記のtcp.iniファイルから値を取得するサンプルです。
GetPrivateProfileString関数を使う場合、Declareステートメントで宣言しておく必要があります。
取得値を保持する変数は事前に拡張しておく必要があるため、Space関数で拡張しています。
取得後はTrimだけでは完全に半角スペースを除去できないため、本来の値だけを取得したい場合はNULL文字がある直前までを取得する必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
Declare PtrSafe Function GetPrivateProfileString Lib _ "kernel32" Alias "GetPrivateProfileStringA" ( _ ByVal lpApplicationName As String, _ ByVal lpKeyName As Any, _ ByVal lpDefault As String, _ ByVal lpReturnedString As String, _ ByVal nSize As Long, _ ByVal lpFileName As String _ ) As Long Sub GetPrivateProfileStringTest() Dim sPath '// INIファイルのパス Dim sValue As String '// 取得値 Dim lSize As Long '// 取得値のサイズ Dim lRet As Long '// 戻り値 lSize = 20 sPath = "C:\test\tcp.ini" '// 取得バッファを初期化 sValue = Space(lSize) '// [TCP_SERVER]セクションの"IP"キーの値を取得 lRet = GetPrivateProfileString("TCP_SERVER", "IP", "non", sValue, lSize, sPath) Debug.Print "[" & sValue & "]" Debug.Print "[" & Trim(sValue) & "]" Debug.Print "[" & Trim(Left(sValue, InStr(sValue, Chr(0)) - 1)) & "]" '// 取得バッファを初期化 sValue = Space(lSize) '// [TCP_CLIENT]セクションの"PORT"キーの値を取得 lRet = GetPrivateProfileString("TCP_CLIENT", "PORT", "non", sValue, lSize, sPath) Debug.Print "[" & sValue & "]" Debug.Print "[" & Trim(sValue) & "]" Debug.Print "[" & Trim(Left(sValue, InStr(sValue, Chr(0)) - 1)) & "]" End Sub |
実行結果
1 2 3 4 5 6 7 8 |
[192.168.20.1 ] [192.168.20.1 ] [192.168.20.1] [192.168.20.1] [50005 ] [50005 ] [50005] [50005] |
取得値から値部分だけを抽出するには
上のサンプルコードでも書いていますが、取得値はそのままではNULL文字や空白スペースなどのゴミが含まれています。
そこで、NULL文字以降を除去するために、Instr関数でNull文字の位置を検索し、Left関数でそこまでを取得するようにします。
「Trim(Left(sValue, InStr(sValue, Chr(0)) – 1))」のように書きます。
GetPrivateProfileString関数の戻り値が値のバイト数であることを利用して、「Left(sValue, lRet)」のように書くことも出来ますが、戻り値は文字数ではなくバイト数のため、値が半角文字だけであれば正しく取得できますが、全角文字が含まれている場合は不要部分を全て除去できません。
GetPrivateProfileString関数には癖がある
サンプルコードの説明でも少し書きましたが、GetPrivateProfileString関数には癖というか問題がいくつかあります。
癖の1つは、Declare宣言しなければならない点ですが、これは他のWin32APIも同様のため、そこまで大変な話ではありません。
2つ目は、取得するための変数が使いづらい、という点です。
事前に拡張しておく必要があるのと、取得後に不要な部分を除去しなければならないという手間が掛かります。
そして3つ目は、処理が遅いという点です。
関数を呼び出しているだけですので目には見えませんが、GetPrivateProfileString関数を実行するたびにファイルのオープンとクローズが発生するため、取得する値が多くなればなるほど、遅延の原因になります。
最後に4つ目として、INIファイルの文字コードがShift-JISに限定される点で、最近ではUTF-8の利用が増えていることを考えると困りものです。
このような癖を考慮して使う必要があります。
処理が遅い点を改善し、高速にINIファイルを取得したい場合は「VBAで高速にINIファイルから値を取得する」をご参照ください。