やりたいこと
元ネタはコチラ:[VBA] 複数のVBAで参照する定数をConfigファイルで一元管理
コンフィグファイルから定数を取得しようというもの。
改善点は2つ
1.複数のコンフィグファイルを読み込めるようにする。
コンフィグファイルの中で、一生変えなくてもよい値と、たまに変更を加えるかもしれない値がある。
それぞれが混在していると予期せぬ修正が入ってしまう可能性があるためファイルを分けることにした。
2.正規表現を持つフォルダから合致するフォルダを検索できるようにする。
メソッド「GetFilePathList()」はファイルの名前に正規表現が「*」含まれている場合、それに合致するファイルのフルパスを取得することができる。しかし、フォルダ名に正規表現が含まれている場合には対応をしていなかったので、それの改修をした。
ソースコード
Option Explicit
' 参照設定
' Windows Script Host Object Model
'
' コンフィグのKeyとValueを保持するMap
Private params As Dictionary
' コンストラクタ
Private Sub Class_Initialize()
End Sub
' デストラクタ
Private Sub Class_Terminate()
End Sub
'
'【処理】
' 指定フォルダ内の全てのコンフィグファイルを読み込む
'
'【引数】
' root_path : confファイルの親フォルダのパス
'
'【返り値】
' なし
'
Public Sub LoadFileList(root_path As String)
Set params = New Dictionary
' コンフィグファイルへのパスを設定する
Dim config_path As String
config_path = root_path & "\conf"
Dim fso As FileSystemObject
Set fso = New FileSystemObject
Dim f As Scripting.File
' 指定フォルダ内の全てのコンフィグファイルを取得する
For Each f In fso.GetFolder(config_path).files
If (f.Name Like "*.conf") Then
Call LoadFile(f.Path)
End If
Next
Set fso = Nothing
End Sub
'
'【処理】
' コンフィグファイルを読み込む
'
'【引数】
' file_path : コンフィグファイルの格納されたフォルダへのパス
'
'【返り値】
' なし
'
Public Sub LoadFile(file_path As String)
Const CHARSET As String = "UTF-8"
' ファイル読み込み
Dim buf As String
Dim ado As New ADODB.Stream
With ado
.CHARSET = CHARSET
.Type = adTypeText
.Open
.LoadFromFile (file_path)
buf = .ReadText
.Close
End With
Set ado = Nothing
Dim lines() As String
lines = Split(buf, vbCrLf)
Dim i
For i = 0 To UBound(lines)
Dim line As String
line = lines(i)
line = Trim(line)
' コメント行
If (Left(line, 1) = "#") Then
' スキップ
' パラメータ追加
ElseIf (InStr(line, "=") > 1) Then
Dim kv() As String
kv = Split(line, "=")
Call params.Add(kv(0), kv(1))
End If
Next
End Sub
' コンフィグ内のKeyに対応するValueを取得する
Public Function ResolveValue(key As String) As String
' キーが存在しない場合、処理を中断する
If (params.Exists(key) = False) Then
Dim err_message As String
err_message = "コンフィグ定義エラー" & vbCrLf & "キー:[" & key & "]がコンフィグファイルに定義されていません。"
Call Err.Raise(1001, "", err_message)
End If
Dim val As String
val = params.Item(key)
' 置換文字列を取得する
Dim reg As RegExp
Set reg = New RegExp
reg.Pattern = ("<.+?>")
reg.Global = True
Dim matches As MatchCollection
Set matches = reg.Execute(val)
Set reg = Nothing
Dim m As Match
For Each m In matches
Dim replace_key As String
Dim replace_val As String
' 置換文字列を取り除く
replace_key = Mid(m.Value, 2, Len(m.Value) - 2)
replace_val = ResolveValue(replace_key)
val = Replace(val, m.Value, replace_val)
Next
' 全ての置換文字列が置換された状態でValueを返却する
ResolveValue = val
End Function
Option Explicit
' コンフィグファイルからキーに対応する値を取得します。
Public Function GetEnv(key As String) As String
Dim c As ConfigAccessor
Set c = New ConfigAccessor
Call c.LoadFileList(ThisWorkbook.Path)
Dim val As String
val = c.ResolveValue(key)
Set c = Nothing
GetEnv = val
End Function
'
' コンフィグファイルからパス/ファイル名を指定し、合致するファイルパスのコレクションを取得する。
' フォルダ/ファイル名には正規表現を指定することも出来る。
' [config]
' template_file_path=C:\Works\
' template_file_name=Dog*.xlsx
' [vba]
' GetSpecificFileName("template_file_path", "template_file_name")
' ⇒ ["C:\Works\Dog123.xlsx", "C:\Works\Dog456.xlsx", "C:\Works\Dog789.xlsx"]
'
Public Function GetFilePathList(key_file_path As String, key_file_name As String) As Collection
Dim fso As FileSystemObject
Set fso = New FileSystemObject
' コンフィグファイルからフォルダパスとファイル名を取得する。
Dim file_path As String
Dim file_name As String
file_path = GetEnv(key_file_path)
file_name = GetEnv(key_file_name)
Dim folderNames() As String
folderNames = Split(file_path, "\")
' GetFolderの引数が"C:\"のみを設定することができないため
' 1,2番目を結合して渡している。
Dim parentFolder As Folder
Set parentFolder = fso.GetFolder(folderNames(0) & "\" & folderNames(1))
Dim currentFolder As Folder
Dim i As Long
' 正規表現に合致するフォルダを取得する
For i = 2 To UBound(folderNames)
For Each currentFolder In parentFolder.SubFolders
Dim hasFounded As Boolean
hasFounded = False
If (currentFolder.Name Like folderNames(i)) Then
Set parentFolder = fso.GetFolder(currentFolder.Path)
hasFounded = True
Exit For
End If
Next
' フォルダが見つからなかった場合、処理を中断する。
If (hasFounded = False) Then
Dim err_message As String
err_message = "指定したフォルダ" & vbCrLf _
& "「" & file_path & "」" & vbCrLf _
& "が見つかりませんでした。コンフィグの設定を見直してください。"
Call Err.Raise(1000, "", err_message)
End If
Next
Dim c As Collection
Set c = New Collection
Dim match_count As Long
Dim currentFile As Scripting.File
' 正規表現に合致するファイルを取得する
For Each currentFile In currentFolder.files
If (currentFile.Name Like file_name) Then
c.Add (currentFile.Path)
End If
Next
Set fso = Nothing
End Function