マクロの設定値を保存する方法として、VBA標準のSaveSetting・GetSetting(レジストリに保存)がありますが、「設定ファイルを開けば中身を確認できるようにしたい」「配布先のPCに設定ファイルごとコピーして使い回したい」という場合には、レジストリよりもテキスト形式のINIファイルの方が扱いやすいことがあります。
この記事では、Windows APIのWritePrivateProfileString関数・GetPrivateProfileString関数を使って、VBAからINIファイルへ設定を書き込み・読み込みする方法を解説します。32bit/64bit両対応の宣言文と、実務で使える関数化のサンプルコード付きで紹介します。
INIファイルとは
INIファイルは、以下のように「セクション」「キー」「値」の3階層で設定を管理するシンプルなテキストファイルです。
[Options]
LastFolder=C:\Data
AutoBackup=True
[Window]
Width=800
Height=600
Windowsには昔からこの形式のファイルを読み書きするAPIが用意されており、VBAからもDeclareステートメントで宣言すれば呼び出すことができます。
APIの宣言(32bit/64bit対応)
標準モジュールの先頭に、以下のAPI宣言を記述します。64bit版Excelにも対応できるよう、#If VBA7 Thenで条件分岐しています。
#If VBA7 Then
Private Declare PtrSafe Function WritePrivateProfileString Lib "kernel32" _
Alias "WritePrivateProfileStringA" _
(ByVal lpApplicationName As String, ByVal lpKeyName As String, _
ByVal lpString As String, ByVal lpFileName As String) As Long
Private Declare PtrSafe Function GetPrivateProfileString Lib "kernel32" _
Alias "GetPrivateProfileStringA" _
(ByVal lpApplicationName As String, ByVal lpKeyName As String, _
ByVal lpDefault As String, ByVal lpReturnedString As String, _
ByVal nSize As Long, ByVal lpFileName As String) As Long
#Else
Private Declare Function WritePrivateProfileString Lib "kernel32" _
Alias "WritePrivateProfileStringA" _
(ByVal lpApplicationName As String, ByVal lpKeyName As String, _
ByVal lpString As String, ByVal lpFileName As String) As Long
Private Declare Function GetPrivateProfileString Lib "kernel32" _
Alias "GetPrivateProfileStringA" _
(ByVal lpApplicationName As String, ByVal lpKeyName As String, _
ByVal lpDefault As String, ByVal lpReturnedString As String, _
ByVal nSize As Long, ByVal lpFileName As String) As Long
#End If
lpApplicationNameがセクション名、lpKeyNameがキー名に対応します。引数名がやや紛らわしいですが、ExcelのApplicationとは無関係です。
使いやすいように関数化する
毎回API関数をそのまま呼び出すと引数が多く扱いづらいため、以下のように書き込み用・読み込み用の関数でラップしておくと便利です。
Private Const INI_PATH As String = "C:\Data\settings.ini"
' INIファイルへ値を書き込む
Sub SaveIniSetting(section As String, key As String, value As String)
WritePrivateProfileString section, key, value, INI_PATH
End Sub
' INIファイルから値を読み込む(未設定時はdefaultValueを返す)
Function GetIniSetting(section As String, key As String, Optional defaultValue As String = "") As String
Dim buffer As String
Dim length As Long
buffer = Space(255)
length = GetPrivateProfileString(section, key, defaultValue, buffer, Len(buffer), INI_PATH)
GetIniSetting = Left(buffer, length)
End Function
GetPrivateProfileStringは、あらかじめ用意しておいたバッファ(buffer)に値を書き込み、実際に取得できた文字数を戻り値として返す仕組みです。そのため、Left関数で実際の文字数分だけ切り出す処理が必要になります。
使用例:前回のフォルダパスを記憶する
先ほど作った関数を使うと、SaveSetting・GetSettingとほぼ同じ感覚でINIファイルを扱えます。
Sub SelectFileWithIniMemory()
Dim lastFolder As String
Dim fd As FileDialog
' INIファイルから前回のフォルダを取得
lastFolder = GetIniSetting("Paths", "LastFolder", "C:\")
Set fd = Application.FileDialog(msoFileDialogFilePicker)
fd.InitialFileName = lastFolder
If fd.Show = -1 Then
Dim selectedPath As String
selectedPath = fd.SelectedItems(1)
MsgBox "選択されたファイル: " & selectedPath
' 次回用にフォルダパスをINIファイルへ保存
SaveIniSetting "Paths", "LastFolder", Left(selectedPath, InStrRev(selectedPath, "\"))
End If
End Sub
初回実行時にINIファイルが存在しなくても、WritePrivateProfileStringが自動的にファイルを新規作成してくれるため、事前にファイルを用意しておく必要はありません。
注意点
- 保存先フォルダに書き込み権限が必要:
Program Files配下など、書き込み制限のあるフォルダをINIファイルの保存先に指定するとエラーになる場合があります。ユーザーのドキュメントフォルダなど、書き込み可能な場所を指定しましょう - バッファサイズに注意:
GetPrivateProfileStringのバッファ(上記コードでは255文字)を超える長い値は正しく取得できません。長い文字列を保存する可能性がある場合はバッファサイズを大きくしてください - レジストリ保存(SaveSetting/GetSetting)との使い分け:設定ファイルを配布先PCへコピーして使い回したい場合や、テキストエディタで内容を確認・編集したい場合はINIファイル、PCごとに独立した設定で十分な場合はレジストリ保存が適しています
まとめ
WritePrivateProfileString・GetPrivateProfileStringを使えば、VBAからINIファイル形式で設定を読み書きできます。関数化しておくことで、レジストリ保存(SaveSetting/GetSetting)と同じような手軽さで扱えるようになるので、配布用マクロの設定管理にぜひ活用してみてください。


コメント